reflect

Guided tour · Reflection & Unsafe · pkg.go.dev →

Inspect and manipulate arbitrary values at runtime. Slow and complex — prefer interfaces and generics when you can.

Type and Value

TypeOf / ValueOf

t := reflect.TypeOf(42)      // int
v := reflect.ValueOf("hi")    // string value
fmt.Println(t.Kind(), v.Kind()) // int string

Kind vs Type

type MyInt int
reflect.TypeOf(MyInt(1)).Kind() // reflect.Int
reflect.TypeOf(MyInt(1)).Name() // "MyInt"

Inspect structs

Walk fields + tags

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}
t := reflect.TypeOf(User{})
for i := 0; i < t.NumField(); i++ {
    f := t.Field(i)
    fmt.Println(f.Name, f.Type, f.Tag.Get("json"))
}

Mutate with reflection

Settable values need pointers

x := 1
v := reflect.ValueOf(&x).Elem() // Elem dereferences
v.SetInt(42)
// x == 42

Dynamic calls

Call a method by name

m := reflect.ValueOf(obj).MethodByName("Greet")
out := m.Call([]reflect.Value{reflect.ValueOf("world")})
fmt.Println(out[0].String())

DeepEqual

Recursive equality

reflect.DeepEqual([]int{1,2}, []int{1,2}) // true
reflect.DeepEqual(map[string]int{"a":1}, map[string]int{"a":1}) // true