英文:
Get name of struct field using reflection
问题
在这里打印"Foo"的方法是什么?在这个例子中,打印的是"string"。
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())
}
在这个例子中,通过使用反射(reflection)来获取结构体字段的类型,并打印出来。在这里,字段"Foo"的类型是"string"。
英文:
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())
}
答案1
得分: 93
你想要的是 val.Type().Field(0).Name
。reflect.Type
上的 Field
方法将返回描述该字段的结构体,其中包括名称和其他信息。
无法通过表示特定字段值的 reflect.Value
来检索字段名称,因为字段名称是包含结构体的属性。
英文:
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.
答案2
得分: 40
我认为获取结构体字段名称的更好方法是:
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)
}
}
有两个提示:
- 在
reflect.ValueOf(a)
之后使用.Elem()
,因为在你的情况下,a
是一个指针。 val.Field(i).Type().Name
与val.Type().Field(i).Name
完全不同。后者可以获取结构体中字段的名称。
希望对你有帮助。
如果你想查看更多示例,请查看我的2分钟文章。
英文:
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
答案3
得分: 32
你需要获取类型定义的字段,而不是值的字段。
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)
}
链接:http://play.golang.org/p/7Bc7MJikbJ
英文:
You need to Get the Field of the Type Definition not of the Value.
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)
}
答案4
得分: 29
请注意,此解决方案引用了一个现已弃用且不再维护的Go模块。它在2018年10月11日被弃用。
使用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"]
}
英文:
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 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"]
}
答案5
得分: 4
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"}
//长而乏味的代码
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("不是结构体")
}
//简写调用
fmt.Println(reflect.TypeOf(*a).Field(0).Name) //如果没有字段存在,可能会引发恐慌
}
英文:
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
}
答案6
得分: 2
你也可以使用https://github.com/fatih/structs。
// 将结构体的字段转换为 []*Field
fields := s.Fields()
for _, f := range fields {
fmt.Printf("字段名: %+v\n", f.Name())
}
英文:
You can also use 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())
}
答案7
得分: 2
你可以使用这个函数,它以struct
作为第一个参数,然后是它的fields
。它返回map
类型,非常方便使用。
如果你使用另一个结构体的字段,不会发生任何事情。
如果你尝试使用不同的类型
,会导致panic
。
注意,字段根据列表有一个序号(从0开始)。结构体中的所有字段都必须以大写字母
开头。
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
}
完整示例和playground
package main
import (
"fmt"
"reflect"
)
type Example struct {
Apple bool
Pear 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 Pear
Apple
Pear
*/
}
英文:
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 main
import (
"fmt"
"reflect"
)
type Example struct {
Apple bool
Pear 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 Pear
Apple
Pear
*/
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论