From 81a5e16e4145916597d598a9fe54c218c607eae0 Mon Sep 17 00:00:00 2001 From: sgf Date: Thu, 25 Apr 2024 21:23:37 +0300 Subject: [PATCH] reflection. Experiment with reflection based on "The Laws of Reflection" See https://go.dev/blog/laws-of-reflection . --- reflection/go.mod | 3 + reflection/hello/hello.go | 23 +++++++ reflection/main.go | 123 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 reflection/go.mod create mode 100644 reflection/hello/hello.go create mode 100644 reflection/main.go diff --git a/reflection/go.mod b/reflection/go.mod new file mode 100644 index 0000000..a9cb442 --- /dev/null +++ b/reflection/go.mod @@ -0,0 +1,3 @@ +module example + +go 1.22.2 diff --git a/reflection/hello/hello.go b/reflection/hello/hello.go new file mode 100644 index 0000000..2d9a0a9 --- /dev/null +++ b/reflection/hello/hello.go @@ -0,0 +1,23 @@ + +package hello + +type H1 struct { + Msg string + Num int +} + +type H2 struct { + Msg string + num int +} +func NewH2(m string) H2 { + return H2{Msg: m, num: 22} +} + +type H3 struct { + msg string + num int +} +func NewH3(m string, n int) H3 { + return H3{msg: m, num: n} +} diff --git a/reflection/main.go b/reflection/main.go new file mode 100644 index 0000000..dae4255 --- /dev/null +++ b/reflection/main.go @@ -0,0 +1,123 @@ +package main + +import ( + "fmt" + "reflect" + "example/hello" +) + +type T struct { + A int + B string +} + +func reflectStruct(v interface{}) { + fmt.Println("====") + s := reflect.ValueOf(v) + if s.Kind() == reflect.Pointer { + fmt.Println("get pointer", s.Type()) + s = s.Elem() + } + typeOfT := s.Type() + fmt.Println("type:", typeOfT) + for i := 0; i < s.NumField(); i++ { + f := s.Field(i) + if typeOfT.Field(i).IsExported() { + fmt.Printf("%d: %s %s = %v (CanSet = %v)\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface(), f.CanSet()) + } else { + fmt.Printf("%d: %s %s = unexported (CanSet = %v, CanAddr = %v)\n", i, typeOfT.Field(i).Name, f.Type(), f.CanSet(), f.CanAddr()) + if f.CanAddr() { + fmt.Println("CanSet Addr", f.Addr().CanSet(), f.Addr().Elem().CanSet()) + if f.Type().Name() == "int" { + fptr := (*int)(f.Addr().UnsafePointer()) + fmt.Printf("... unsafe value: %v \n", *fptr) + *fptr = 77 + fmt.Printf("... unsafe set: %v \n", *fptr) + } else if f.Type().Name() == "string" { + fptr := (*string)(f.Addr().UnsafePointer()) + fmt.Printf("... unsafe value: %v \n", *fptr) + *fptr = "brrr" + fmt.Printf("... unsafe set: %v \n", *fptr) + } + } + } + } +} + +func main() { + var x1 float64 = 3.4 + fmt.Println("type:", reflect.TypeOf(x1)) + v1 := reflect.ValueOf(x1) + fmt.Println("value:", v1.String()) + fmt.Println("type:", v1.Type()) + fmt.Println("kind is float64:", v1.Kind() == reflect.Float64) + fmt.Println("value:", v1.Float()) + + fmt.Println("====") + var x2 uint8 = 'x' + v2 := reflect.ValueOf(x2) + fmt.Println("type:", v2.Type()) // uint8. + fmt.Println("kind is uint8: ", v2.Kind() == reflect.Uint8) // true. + fmt.Println("value:", v2.Uint()) + x2 = uint8(v2.Uint()) // v2.Uint returns a uint64. + fmt.Println("x2:", x2) + + fmt.Println("====") + type MyInt int + var x3 MyInt = 7 + v3 := reflect.ValueOf(x3) + fmt.Println("type:", v3.Type()) + fmt.Println("kind is int: ", v3.Kind() == reflect.Int) // true. + fmt.Println("value:", v3.Int()) + + fmt.Println("====") + y1 := v1.Interface().(float64) // y will have type float64. + fmt.Printf("%v %T\n", y1, y1) + fmt.Printf("%v %T\n", v1.Interface(), v1.Interface()) + fmt.Printf("value is %7.1e\n", v1.Interface()) + + fmt.Println("====") + var x4 float64 = 3.4 + v4 := reflect.ValueOf(x4) + //v4.SetFloat(7.1) // Error: will panic. + + fmt.Println("settability of v4:", v4.CanSet()) + + p4 := reflect.ValueOf(&x4) // Note: take the address of x. + fmt.Println("type of p4:", p4.Type()) + fmt.Println("settability of p4:", p4.CanSet()) + fmt.Println("settability of *p4:", p4.Elem().CanSet()) + p4.Elem().SetFloat(7.1) + fmt.Println("x4:", x4) + + fmt.Println("====") + t := T{23, "skidoo"} + s := reflect.ValueOf(&t).Elem() + typeOfT := s.Type() + fmt.Println("type:", typeOfT) + for i := 0; i < s.NumField(); i++ { + f := s.Field(i) + fmt.Printf("%d: %s %s = %v\n", i, + typeOfT.Field(i).Name, f.Type(), f.Interface()) + } + s.Field(0).SetInt(77) + s.Field(1).SetString("Sunset Strip") + fmt.Println("t is now", t) + + fmt.Println() + h1 := hello.H1{"H1", 11} + reflectStruct(h1) + reflectStruct(&h1) + fmt.Println("got:", h1) + + h2 := hello.NewH2("H2") + reflectStruct(h2) + reflectStruct(&h2) + fmt.Println("got:", h2) + + h3 := hello.NewH3("H3", 11) + reflectStruct(h3) + reflectStruct(&h3) + fmt.Println("got:", h3) + +} -- 2.20.1