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

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

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

person RAFJR    schedule 05.10.2016    source источник


Ответы (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("%+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()< /a>, сравнивая результат с 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 можно найти в записи блога: Законы рефлексии.

person icza    schedule 05.10.2016