如何知道我可以從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
感謝您的詳細解答,包括博客文章。很有幫助。 –