【问题标题】:Get name of struct field using reflection使用反射获取结构字段的名称
【发布时间】:2014-08-11 19:04:07
【问题描述】:

这里打印“Foo”的方式是什么?在本例中,打印的是“字符串”。

http://play.golang.org/p/ZnK6PRwEPp

type A struct {
    Foo string
}

func (a *A) PrintFoo() {
    fmt.Println("Foo value is " + a.Foo)
}

func main() {
    a := &A{Foo: "afoo"}
    val := reflect.Indirect(reflect.ValueOf(a))
    fmt.Println(val.Field(0).Type().Name())
}

【问题讨论】:

    标签: go


    【解决方案1】:

    你想要val.Type().Field(0).Namereflect.Type 上的 Field 方法将返回一个描述该字段的结构,其中包括名称等信息。

    无法检索代表特定字段值的reflect.Value 的字段名称,因为这是包含结构的属性。

    【讨论】:

    • “无法检索代表特定字段值的 reflect.Value 的字段名称” - 为什么会这样?类型和名称不是字段本身的一部分吗?
    • @sat 只要您拥有特定字段的reflect.Value,它就与任何其他变量没有什么不同。只有结构有关于它的字段的信息。
    • @sat:在您的示例中,val.Field(0) 与任何其他字符串的 reflect.Value 没有什么不同。它不会“记住”它是结构的一部分。
    • @JamesHenstridge - 但我真的不需要它来记住它属于一个结构。我试图打印的只是使用反射的字段本身的变量名称(无论它是否是结构的一部分)。对不起,如果它真的是一个新手问题
    • 事情就是这样:变量没有名字——它只是内存中的一个位置。
    【解决方案2】:

    您需要获取类型定义的字段而不是值。

    http://play.golang.org/p/7Bc7MJikbJ

    package main
    
    import "fmt"
    import "reflect"
    
    type A struct {
        Foo string
    }
    
    func (a *A) PrintFoo() {
        fmt.Println("Foo value is " + a.Foo)
    }
    
    func main() {
        a := &A{Foo: "afoo"}
        val := reflect.Indirect(reflect.ValueOf(a))
        fmt.Println(val.Type().Field(0).Name)
    }
    

    【讨论】:

    • 很好的例子,但你的答案缺乏解释。
    【解决方案3】:

    使用structs 包的新Names 方法,它更加容易:

    package main
    
    import (
        "fmt"
    
        "github.com/fatih/structs"
    )
    
    type A struct {
        Foo string
        Bar int
    }
    
    func main() {
        names := structs.Names(&A{})
        fmt.Println(names) // ["Foo", "Bar"]
    }
    

    【讨论】:

    • 你应该提到它是你自己的包。
    • @swdon 当 Fatih Arslan 构建一个库时,它几乎就像是标准库一样。
    • 提到这是我自己的包?包名本身已经有了我的名字,我不知道我还能说什么:)
    • 这个包不再维护
    【解决方案4】:

    我认为在结构中获取字段名称的更好方法是

    func main() {
        a := &A{Foo: "afoo"}
        val := reflect.ValueOf(a).Elem()
        for i:=0; i<val.NumField();i++{
            fmt.Println(val.Type().Field(i).Name)
        }
    }
    

    有两个提示:

    1. reflect.ValueOf(a) 之后使用.Elem(),因为在您的情况下,a 是一个指针。
    2. val.Field(i).Type().Nameval.Type().Field(i).Name 完全不同。后者可以获取struct中的字段名称

    希望对你有帮助..

    如果您想查看更多案例,请查看my 2mins article

    【讨论】:

      【解决方案5】:

      你也可以使用https://github.com/fatih/structs

      // Convert the fields of a struct to a []*Field
      fields := s.Fields()
      
      for _, f := range fields {
          fmt.Printf("field name: %+v\n", f.Name())
      }
      

      【讨论】:

        【解决方案6】:
        package main
        
        import "fmt"
        import "reflect"
        
        type A struct {
            Foo string
        }
        
        func (a *A) PrintFoo() {
            fmt.Println("Foo value is " + a.Foo)
        }
        
        func main() {
            a := &A{Foo: "afoo"}
        
            //long and bored code
            t := reflect.TypeOf(*a)
            if t.Kind() == reflect.Struct {
                for i := 0; i < t.NumField(); i++ {
                    fmt.Println(t.Field(i).Name)
                }
            } else {
                fmt.Println("not a stuct")
            }
        
            //shorthanded call
            fmt.Println(reflect.TypeOf(*a).Field(0).Name)//can panic if no field exists
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-06-17
          • 1970-01-01
          • 2022-01-08
          • 1970-01-01
          • 2013-04-24
          • 2021-12-13
          • 1970-01-01
          相关资源
          最近更新 更多