Получить все поля из интерфейса

#go #reflection #struct #reply

#Вперед #отражение #структура #Ответить

Вопрос:

Как мне узнать, к каким полям я могу получить доступ из reply объекта / интерфейса? Я попробовал отражение, но, похоже, сначала вам нужно знать имя поля. Что, если мне нужно знать все доступные мне поля?

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

Ответ №1:

Вы можете использовать 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("% vn", 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 значение, которое является a 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.

Примечание: часто указатель на struct заключен в интерфейс. В таких случаях вы можете использовать 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.

Для подробного ознакомления с отражением Go прочитайте сообщение в блоге: Законы отражения.