Tags: #go #golang #pointer #struct #reflection #iterate #fields
package main
import (
"fmt"
"reflect"
)
func main() {
f := "foo"
b := "bar"
x := struct {
Foo *string
Bar *string
}{&f, &b}
// NOTE: pass value as reflect.Indirect(x) if x is a struct pointer
v := reflect.ValueOf(x)
// prints the value which is the same as %+v on the struct itself and the type is something like *main.struct{...}
fmt.Printf("reflect: %+v (type: %+v)\n", v, v.Type())
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
// v.Field == memory address of first struct field
fmt.Println("Field:", v.Field, v.FieldByIndex([]int{0}), v.FieldByIndex([]int{0}).Addr())
// .Interface() will panic on unexported field!
if !field.CanInterface() {
continue
}
if field.Kind() == reflect.Bool {
// do something with a boolean type field
// see also: https://golang.org/pkg/reflect/#Kind const iota
if field.CanSet() {
field.Set(reflect.ValueOf(true))
}
}
fmt.Printf("name: %+v, value: %+v (type: %T, kind: %+v)\n",
v.Type().Field(i).Name, // Name attribute gives us the struct's key
field.Elem(), // Elem() dereferences the pointer value
field.Interface()), // Interface() provides the interface itself (e.g. {Foo: "foo", Bar: "bar"})
field.Kind() // Kind() give back the type of the field
}
/*
name: Foo, value: foo (*string)
name: Bar, value: bar (*string)
*/
}