2016-10-05 5 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.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.

+1

Точно, как я хотел бы получить ответ! Благодарим вас за дополнительную милю и предоставим рабочий код. – RAFJR

+1

Благодарим вас за подробный ответ, включая сообщение в блоге. Очень полезно. –