Подтвердить что ты не робот

Итерации через поля структуры в Go

В принципе, единственный способ (который я знаю) для итерации значений полей struct выглядит так:

type Example struct {
    a_number uint32
    a_string string
}

//...

r := &Example{(2 << 31) - 1, "...."}:
for _, d:= range []interface{}{ r.a_number, r.a_string, } {
  //do something with the d
}

Мне было интересно, если есть лучший и более универсальный способ достижения []interface{}{ r.a_number, r.a_string, }, поэтому мне не нужно перечислять каждый параметр по отдельности или, альтернативно, есть лучший способ для цикла через структуру?

Я попытался просмотреть пакет reflect, но я ударил стену, потому что я не уверен, что делать, как только я извлеките reflect.ValueOf(*r).Field(0).

Спасибо!

4b9b3361

Ответ 1

После того, как вы извлекли reflect.Value в поле, используя Field(i), вы можете получить значение интерфейса из него, вызывая Interface(). Указанное значение интерфейса затем представляет собой значение поля.

Нет функции для преобразования значения поля в конкретный тип, как есть, как вы знаете, никаких дженериков в пути. Таким образом, нет функции с сигнатурой GetValue() T с T является типом этого поля (которое, конечно, меняется в зависимости от поля).

Ближе всего вы можете достичь в go GetValue() interface{}, и это именно то, что reflect.Value.Interface() предлагает.

Следующий код иллюстрирует, как получить значения каждого экспортируемого поля в структуре используя отражение (play):

import (
    "fmt"
    "reflect"
)

func main() {
    x := struct{Foo string; Bar int }{"foo", 2}

    v := reflect.ValueOf(x)

    values := make([]interface{}, v.NumField())

    for i := 0; i < v.NumField(); i++ {
        values[i] = v.Field(i).Interface()
    }

    fmt.Println(values)
}

Ответ 2

Если вы хотите пройтись по полям и значениям структуры, вы можете использовать приведенный ниже код Go в качестве ссылки.

package main

import (
    "fmt"
    "reflect"
)

type Student struct {
    Fname  string
    Lname  string
    City   string
    Mobile int64
}

func main() {
    s := Student{"Chetan", "Kumar", "Bangalore", 7777777777}
    v := reflect.ValueOf(s)
    typeOfS := v.Type()

    for i := 0; i< v.NumField(); i++ {
        fmt.Printf("Field: %s\tValue: %v\n", typeOfS.Field(i).Name, v.Field(i).Interface())
    }
}

Бегать на детской площадке

Примечание. Если поля в вашей структуре не экспортируются, то v.Field(i).Interface() вызовет panic: reflect.Value.Interface: cannot return value obtained from unexported field or method.