【问题标题】:Get all fields from an interface从接口获取所有字段
【发布时间】:2016-10-05 06:05:56
【问题描述】:

我如何知道可以从reply 对象/接口访问的字段?我尝试了反射,但似乎您必须先知道字段名称。如果我需要知道所有可用的字段怎么办?

// Do sends a command to the server and returns the received reply.
Do(commandName string, args ...interface{}) (reply interface{}, err error)

【问题讨论】:

    标签: go reflection struct reply


    【解决方案1】:

    您可以使用reflect.TypeOf() 函数获取reflect.Type 类型描述符。从那里,您可以列出存储在界面中的动态值的字段。

    例子:

    type Point struct {
        X int
        Y int
    }
    
    var reply interface{} = Point{1, 2}
    t := reflect.TypeOf(reply)
    for i := 0; i < t.NumField(); i++ {
        fmt.Printf("%+v\n", t.Field(i))
    }
    

    输出:

    {Name:X PkgPath: Type:int Tag: Offset:0 Index:[0] Anonymous:false}
    {Name:Y PkgPath: Type:int Tag: Offset:4 Index:[1] Anonymous:false}
    

    Type.Field() 调用的结果是 reflect.StructField 值,它是 struct,其中包含字段名称:

    type StructField struct {
        // Name is the field name.
        Name string
        // ...
    }
    

    如果你还想要字段的值,你可以使用reflect.ValueOf()得到一个reflect.Value(),然后你可以使用Value.Field()Value.FieldByName()

    v := reflect.ValueOf(reply)
    for i := 0; i < v.NumField(); i++ {
        fmt.Println(v.Field(i))
    }
    

    输出:

    1
    2
    

    Go Playground 上试用。

    注意:指向结构的指针通常包装在接口中。在这种情况下,您可以使用 Type.Elem()Value.Elem() 来“导航”到指向的类型或值:

    t := reflect.TypeOf(reply).Elem()
    
    v := reflect.ValueOf(reply).Elem()
    

    如果不知道是不是指针,可以用Type.Kind()Value.Kind()检查,和reflect.Ptr比较结果:

    t := reflect.TypeOf(reply)
    if t.Kind() == reflect.Ptr {
        t = t.Elem()
    }
    
    // ...
    
    v := reflect.ValueOf(reply)
    if v.Kind() == reflect.Ptr {
        v = v.Elem()
    }
    

    Go Playground 上试试这个变体。

    关于 Go 反射的详细介绍,请阅读博文:The Laws of Reflection

    【讨论】:

      猜你喜欢
      • 2018-03-29
      • 2018-06-24
      • 2015-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多