Итерации через поля структуры в 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)
.
Спасибо!
Ответы
Ответ 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.