去反映字段索引-单索引与切片



reflect.StructFieldIndex字段类型为[]int。关于这一点的文档有点令人困惑:

    Index     []int     // index sequence for Type.FieldByIndex

当然,Type.FieldByIndex也像预期的那样,对其行为有更清晰的解释:

    // 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

但是,也有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

所以它们各自的行为是非常清楚的。

我的问题:究竟在哪些领域/什么情况下,reflect.StructField将有Indexlen(field.Index) > 1 ?这是否支持枚举嵌入字段(可通过父字段中的匿名字段访问)?在其他情况下也会发生吗?(即。如果!field.Anonymous,那么我们可以使用field.Index[0]作为Field(i int)的参数,这是安全的吗?)

它可以递归地引用嵌入或非嵌入结构中的字段:

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
}

所以我一直在寻找这个问题的答案,我真的没能找到任何东西。为了解释为什么上面的答案不令人满意,我有一个例子:

package main
import (
    "fmt"
    "reflect"
)
type (
    A struct {
        W int
        X int
    }
    B struct {
        Y int
        A A
    }
    C struct {
        B B
        Z int
    }
)
func main() {
    b := B{1, A{2, 3}}
    c := C{b, 4}
    bt := reflect.TypeOf(b)
    ct := reflect.TypeOf(c)
    ba := bt.FieldByIndex([]int{1, 0})
    ca := ct.FieldByIndex([]int{0, 1, 0})
    fmt.Println("B > A = ", ba.Index)
    fmt.Println("C > B > A = ", ca.Index)
}

输出为:

B比;A = [0]
C比;B在A = [0]

用StructField的描述。文档中给出的索引(

)

Index []int//类型的索引序列。FieldByIndex

)可能会假设输出在某种程度上对应于通过FieldByIndex方法检索相同的字段,并且由于该方法是为嵌套字段设计的,因此上面的输出可能会令人困惑。如果Index总是长度为1的[]int,为什么还要使用数组呢?如果它只与它的直接父级相关,为什么不存储单个int ?

答案可能比我们(那些对此感到困惑的人)预期的要简单。Index的值必须经常用作FieldByIndex的参数,因此为了方便起见,它被存储在数组中。

下面是一个例子。为了回答这个问题,我深入研究了反射测试。

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]
}

相关内容

  • 没有找到相关文章

最新更新