reflect.StructField
has an Index
field that is typed []int
. The documentation on this is slightly confounding:
Index []int // index sequence for Type.FieldByIndex
And of course Type.FieldByIndex
follows suit as expected, with the somewhat clearer explanation of its behavior:
// FieldByIndex returns the nested field corresponding
// to the index sequence. It is equivalent to calling Field
// successively for each index i.
// It panics if the type's Kind is not Struct.
FieldByIndex(index []int) StructField
But, there is also Type.Field()
:
// Field returns a struct type's i'th field.
// It panics if the type's Kind is not Struct.
// It panics if i is not in the range [0, NumField()).
Field(i int) StructFiel
So the behavior of those respectively is very clear.
My question: Exactly for which fields / what circumstances will a reflect.StructField
have an Index
with len(field.Index) > 1
? Is this there to support enumerating embedded fields (reachable through an anonymous field in the parent)? Does it happen in other cases? (ie. is it safe to assume if !field.Anonymous
, then we can just use field.Index[0]
as an argument to Field(i int)
?)
It can refer to fields in embedded or non embedded structs, recursively:
type Foo struct {
Bar string
}
type Baz struct {
Zoo Foo
}
func main() {
b := Baz{Zoo:Foo{"foo"}}
v := reflect.ValueOf(b)
fmt.Println(v.FieldByIndex([]int{0})) //output: <main.Foo Value>
fmt.Println(v.FieldByIndex([]int{0, 0})) //output: foo
}
Here is an example. To answer this question, I've dig into reflect tests.
package main
import (
"fmt"
"reflect"
)
type (
Bar struct {
Val string
}
Foo struct {
Bar
}
)
func main() {
t := reflect.TypeOf(Foo{})
f, _ := t.FieldByName("Val")
fmt.Println(f.Index) // [0 0]
}