reflection. Experiment with reflection based on "The Laws of Reflection"
authorsgf <sgf.dma@gmail.com>
Thu, 25 Apr 2024 18:23:37 +0000 (21:23 +0300)
committersgf <sgf.dma@gmail.com>
Thu, 2 May 2024 15:24:26 +0000 (18:24 +0300)
See https://go.dev/blog/laws-of-reflection .

reflection/go.mod [new file with mode: 0644]
reflection/hello/hello.go [new file with mode: 0644]
reflection/main.go [new file with mode: 0644]

diff --git a/reflection/go.mod b/reflection/go.mod
new file mode 100644 (file)
index 0000000..a9cb442
--- /dev/null
@@ -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 (file)
index 0000000..2d9a0a9
--- /dev/null
@@ -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 (file)
index 0000000..dae4255
--- /dev/null
@@ -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)
+
+}