What is the way of printing "Foo" here? In this example, what prints is "string".
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())}
Best Answer
You want val.Type().Field(0).Name
. The Field
method on reflect.Type
will return a struct describing that field, which includes the name, among other information.
There is no way to retrieve the field name for a reflect.Value
representing a particular field value, since that is a property of the containing struct.
I think the better way to get the fields' name in the struct is
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)}}
There are two tips:
- use
.Elem()
after youreflect.ValueOf(a)
, because in your case, a is a pointer. val.Field(i).Type().Name
is totally different fromval.Type().Field(i).Name
. The latter one can get the name of the field in the struct
Hope that it is helpful..
If you want to have a look at more cases, please check my 2mins article
You need to Get the Field of the Type Definition not of the Value.
http://play.golang.org/p/7Bc7MJikbJ
package mainimport "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)}
Note that this solution references a Go module which is now deprecated, and is no longer being maintained. It was deprecated as of Oct 11, 2018.
With the new Names
method of the structs package it's even easier:
package mainimport ("fmt""github.com/fatih/structs")type A struct {Foo stringBar int}func main() {names := structs.Names(&A{})fmt.Println(names) // ["Foo", "Bar"]}
package mainimport "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 codet := 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 callfmt.Println(reflect.TypeOf(*a).Field(0).Name)//can panic if no field exists}
You can use this function, which takes the struct
as the first parameter, and then its fields
. It returns the map
type, which is convenient to use
If you use fields from another structure, nothing will happen
If you try to use a different type
, it will cause panic
Note that the field has an ordinal number according to the list (starting from 0). All fields in the structure must start with uppercase
func GetStructFieldName(Struct interface{}, StructField ...interface{}) (fields map[int]string) {fields = make(map[int]string)s := reflect.ValueOf(Struct).Elem()for r := range StructField {f := reflect.ValueOf(StructField[r]).Elem()for i := 0; i < s.NumField(); i++ {valueField := s.Field(i)if valueField.Addr().Interface() == f.Addr().Interface() {fields[i] = s.Type().Field(i).Name}}}return fields}
Full example and playground
package mainimport ("fmt""reflect")type Example struct {Apple boolPear int}func GetStructFieldName(Struct interface{}, StructField ...interface{}) (fields map[int]string) {fields = make(map[int]string)for r := range StructField {s := reflect.ValueOf(Struct).Elem()f := reflect.ValueOf(StructField[r]).Elem()for i := 0; i < s.NumField(); i++ {valueField := s.Field(i)if valueField.Addr().Interface() == f.Addr().Interface() {fields[i] = s.Type().Field(i).Name}}}return fields}func main() {e := Example{}names := GetStructFieldName(&e, &e.Apple, &e.Pear)fmt.Println(names)fmt.Println(names[0], names[1])for i := range names {fmt.Println(names[i])}/* Output:map[0:Apple 1:Pear]Apple PearApplePear*/}
You can also use https://github.com/fatih/structs
// Convert the fields of a struct to a []*Fieldfields := s.Fields()for _, f := range fields {fmt.Printf("field name: %+v\n", f.Name())}