如何知道我可以从reply
对象/接口访问的字段?我尝试了反思,但似乎你必须先知道字段名称。如果我需要知道所有可用的字段,该怎么办?从接口获取所有字段
// Do sends a command to the server and returns the received reply.
Do(commandName string, args ...interface{}) (reply interface{}, err error)
如何知道我可以从reply
对象/接口访问的字段?我尝试了反思,但似乎你必须先知道字段名称。如果我需要知道所有可用的字段,该怎么办?从接口获取所有字段
// Do sends a command to the server and returns the received reply.
Do(commandName string, args ...interface{}) (reply interface{}, err error)
可以使用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。
准确地说,我希望得到回答!感谢您为此付出额外努力并提供有效的代码。 – RAFJR
感谢您的详细解答,包括博客文章。很有帮助。 –