Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
88
Task/Break-OO-privacy/Go/break-oo-privacy-1.go
Normal file
88
Task/Break-OO-privacy/Go/break-oo-privacy-1.go
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type foobar struct {
|
||||
Exported int // In Go identifiers that are capitalized are exported,
|
||||
unexported int // while lowercase identifiers are not.
|
||||
}
|
||||
|
||||
func main() {
|
||||
obj := foobar{12, 42}
|
||||
fmt.Println("obj:", obj)
|
||||
|
||||
examineAndModify(&obj)
|
||||
fmt.Println("obj:", obj)
|
||||
|
||||
anotherExample()
|
||||
}
|
||||
|
||||
// For simplicity this skips several checks. It assumes the thing in the
|
||||
// interface is a pointer without checking (v.Kind()==reflect.Ptr),
|
||||
// it then assumes it is a structure type with two int fields
|
||||
// (v.Kind()==reflect.Struct, f.Type()==reflect.TypeOf(int(0))).
|
||||
func examineAndModify(any interface{}) {
|
||||
v := reflect.ValueOf(any) // get a reflect.Value
|
||||
v = v.Elem() // dereference the pointer
|
||||
fmt.Println(" v:", v, "=", v.Interface())
|
||||
t := v.Type()
|
||||
// Loop through the struct fields
|
||||
fmt.Printf(" %3s %-10s %-4s %s\n", "Idx", "Name", "Type", "CanSet")
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
f := v.Field(i) // reflect.Value of the field
|
||||
fmt.Printf(" %2d: %-10s %-4s %t\n", i,
|
||||
t.Field(i).Name, f.Type(), f.CanSet())
|
||||
}
|
||||
|
||||
// "Exported", field 0, has CanSet==true so we can do:
|
||||
v.Field(0).SetInt(16)
|
||||
// "unexported", field 1, has CanSet==false so the following
|
||||
// would fail at run-time with:
|
||||
// panic: reflect: reflect.Value.SetInt using value obtained using unexported field
|
||||
//v.Field(1).SetInt(43)
|
||||
|
||||
// However, we can bypass this restriction with the unsafe
|
||||
// package once we know what type it is (so we can use the
|
||||
// correct pointer type, here *int):
|
||||
vp := v.Field(1).Addr() // Take the fields's address
|
||||
up := unsafe.Pointer(vp.Pointer()) // … get an int value of the address and convert it "unsafely"
|
||||
p := (*int)(up) // … and end up with what we want/need
|
||||
fmt.Printf(" vp has type %-14T = %v\n", vp, vp)
|
||||
fmt.Printf(" up has type %-14T = %#0x\n", up, up)
|
||||
fmt.Printf(" p has type %-14T = %v pointing at %v\n", p, p, *p)
|
||||
*p = 43 // effectively obj.unexported = 43
|
||||
// or an incr all on one ulgy line:
|
||||
*(*int)(unsafe.Pointer(v.Field(1).Addr().Pointer()))++
|
||||
|
||||
// Note that as-per the package "unsafe" documentation,
|
||||
// the return value from vp.Pointer *must* be converted to
|
||||
// unsafe.Pointer in the same expression; the result is fragile.
|
||||
//
|
||||
// I.e. it is invalid to do:
|
||||
// thisIsFragile := vp.Pointer()
|
||||
// up := unsafe.Pointer(thisIsFragile)
|
||||
}
|
||||
|
||||
// This time we'll use an external package to demonstrate that it's not
|
||||
// restricted to things defined locally. We'll mess with bufio.Reader's
|
||||
// interal workings by happening to know they have a non-exported
|
||||
// "err error" field. Of course future versions of Go may not have this
|
||||
// field or use it in the same way :).
|
||||
func anotherExample() {
|
||||
r := bufio.NewReader(os.Stdin)
|
||||
|
||||
// Do the dirty stuff in one ugly and unsafe statement:
|
||||
errp := (*error)(unsafe.Pointer(
|
||||
reflect.ValueOf(r).Elem().FieldByName("err").Addr().Pointer()))
|
||||
*errp = errors.New("unsafely injected error value into bufio inner workings")
|
||||
|
||||
_, err := r.ReadByte()
|
||||
fmt.Println("bufio.ReadByte returned error:", err)
|
||||
}
|
||||
17
Task/Break-OO-privacy/Go/break-oo-privacy-2.go
Normal file
17
Task/Break-OO-privacy/Go/break-oo-privacy-2.go
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
link printf
|
||||
|
||||
procedure main()
|
||||
(x := foo(1,2,3)).print() # create and show a foo
|
||||
printf("Fieldnames of foo x : ") # show fieldnames
|
||||
every printf(" %i",fieldnames(x)) # __s (self), __m (methods), vars
|
||||
printf("\n")
|
||||
printf("var 1 of foo x = %i\n", x.var1) # read var1 from outside x
|
||||
x.var1 := -1 # change var1 from outside x
|
||||
x.print() # show we changed it
|
||||
end
|
||||
|
||||
class foo(var1,var2,var3) # class with no set/read methods
|
||||
method print()
|
||||
printf("foo var1=%i, var2=%i, var3=%i\n",var1,var2,var3)
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue