2016-10-05 11 views
4

replyオブジェクト/インターフェイスからアクセスできるフィールドを知る方法を教えてください。私は反射を試みたが、フィールド名を最初に知っていなければならないようだ。利用可能なすべてのフィールドを知る必要がある場合はどうすればよいですか?インターフェイスのすべてのフィールドを取得する

// Do sends a command to the server and returns the received reply. 
Do(commandName string, args ...interface{}) (reply interface{}, err error) 

答えて

13

あなたはreflect.Type型記述子を取得するためにreflect.TypeOf()機能を使用することができます。そこから、インターフェイスに格納されている動的値のフィールドを一覧表示できます。

例:

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()呼び出しの結果は、とりわけ、フィールドの名前を含む、structあるreflect.StructField値であり、

type StructField struct { 
    // Name is the field name. 
    Name string 
    // ... 
} 

値フィールドで、あなたはreflect.Value()を取得するためにreflect.ValueOf()を使用することができ、その後、あなたが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をご覧ください。

+1

正確に私は答えたいと思っていました!余分なマイルのために働いて、働くコードを提供してくれてありがとう。 – RAFJR

+1

ブログ記事を含む詳細な回答ありがとうございます。非常に役立ちます。 –

関連する問題