Use Value.Field(index) to obtain a struct field's reflect.Value. The index must match the field position returned by Type.Field(index), linking a struct's type metadata to its runtime value. section 13.1.3
A reflective struct walker typically follows this sequence:
- Convert an interface value with reflect.ValueOf(). section 13.1.3
- Use reflect.Indirect() when the value may be a pointer. section 13.1.3
- Iterate field indexes, obtain metadata with Type.Field(), and obtain corresponding values with Value.Field(). section 13.1.3
Listing 13.7 Recursively examining a value
func main() {
fmt.Println("Walking a simple integer")
var one MyInt = 1 #1
walk(one, 0) #1
fmt.Println("Walking a simple struct")
two := struct{ Name string }{"foo"} #2
walk(two, 0) #2
fmt.Println("Walking a struct with struct fields") #2
p := &Person{ #3
Name: &Name{"Count", "Tyrone", "Rugen"
},
Address: &Address{"Humperdink Castle",
"Florian"},
}
walk(p, 0)
}
type MyInt int
type Person struct {
Name *Name
Address *Address
}
type Name struct {
Title, First, Last string
}
type Address struct {
Street, Region string
}
func walk(u interface{}, depth int) { #4
val := reflect.Indirect(reflect.ValueOf(u)) #5
t := val.Type() #6
tabs := strings.Repeat("\t", depth+1) #7
fmt.Printf("%sValue is type %q (%s)\n", tabs, t, val.Kind())
if val.Kind() == reflect.Struct { #8
for i := 0; i < t.NumField(); i++ {
field := t.Field(i) #9
fieldVal := reflect.Indirect
(val.Field(i))
tabs := strings.Repeat("\t", depth+2)
fmt.Printf("%sField %q is type %q (%s)\n",
tabs, field.Name, field.Type, fieldVal.Kind())
if fieldVal.Kind() ==
reflect.Struct { #10
walk(fieldVal.Interface(), depth+1) #10
} #10
}
}
}
Follow the recursive walker as it inspects primitive values, simple structs, and pointer-containing nested structs. section 13.1.3
