Go中通过反射为struct成员赋值
Assigning a value to struct member through reflection in Go
我有一个包含成员 A、B、C 字符串的结构 v。使用反射,我可以获得字段的名称及其值:
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
// gets us a StructField
fi := typ.Field(i)
fieldname := fi.Name
fmt.Println(fieldname)
val := fmt.Sprintf("%v", v.Field(i).Interface())
}
既然我有名字,并且可以得到值OUT,我可以给字段赋新值吗?我想做的基本上是:
v.Field(fieldname).Interface() = "new value"
但这显然行不通。如果您只知道字段的名称,是否可以将值分配给结构?
实际上,我试图将 map[string]string
中的值分配给结构中的相应字段,其中结构和映射定义可能会随着时间的推移而扩展变化,并且映射可能包含更多,或者小于结构的值。我考虑过这样做 w/JSON,但这种方法让我有点感冒,因为使用反射来获得 "almost" 是多么容易!
谢谢,
肯
是的,有可能。
简介
由于要访问和修改变量(或字段)的值,所以需要使用reflect.Value
type instead of reflect.Type
. You can acquire it with reflect.ValueOf()
。另外,为了通过反射修改它,您需要传递 struct
的地址(指针)或您要修改的值(否则您只能读取它而不能修改它)。
但是你不想修改address/pointer而是pointed值,所以你必须从Value
"navigate"指向指向变量(结构)的 Value
的指针,这就是 Value.Elem()
的用途。看起来像这样:reflect.ValueOf(&s).Elem()
你可以使用 Value.FieldByName()
方法获取结构字段的 Value
,因为我们将指针的地址传递给 ValueOf()
函数将是 可设置.
代码
代码比介绍简单多了,看懂了。您也可以在 Go Playground:
上尝试
var s struct {
A, B, C string
}
s.A, s.B, s.C = "a1", "b2", "c3"
fmt.Println("Before: ", s)
v := reflect.ValueOf(&s).Elem()
v.FieldByName("A").SetString("2a")
v.FieldByName("B").SetString("2b")
v.FieldByName("C").SetString("2c")
fmt.Println("After: ", s)
// Using a map:
m := map[string]string{"A": "ma", "B": "mb", "C": "mc"}
for mk, mv := range m {
v.FieldByName(mk).SetString(mv)
}
fmt.Println("From Map:", s)
输出:
Before: {a1 b2 c3}
After: {2a 2b 2c}
From Map: {ma mb mc}
我建议阅读此博客 post 以了解 Go 中反射的基础知识:
我有一个包含成员 A、B、C 字符串的结构 v。使用反射,我可以获得字段的名称及其值:
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
// gets us a StructField
fi := typ.Field(i)
fieldname := fi.Name
fmt.Println(fieldname)
val := fmt.Sprintf("%v", v.Field(i).Interface())
}
既然我有名字,并且可以得到值OUT,我可以给字段赋新值吗?我想做的基本上是:
v.Field(fieldname).Interface() = "new value"
但这显然行不通。如果您只知道字段的名称,是否可以将值分配给结构?
实际上,我试图将 map[string]string
中的值分配给结构中的相应字段,其中结构和映射定义可能会随着时间的推移而扩展变化,并且映射可能包含更多,或者小于结构的值。我考虑过这样做 w/JSON,但这种方法让我有点感冒,因为使用反射来获得 "almost" 是多么容易!
谢谢, 肯
是的,有可能。
简介
由于要访问和修改变量(或字段)的值,所以需要使用reflect.Value
type instead of reflect.Type
. You can acquire it with reflect.ValueOf()
。另外,为了通过反射修改它,您需要传递 struct
的地址(指针)或您要修改的值(否则您只能读取它而不能修改它)。
但是你不想修改address/pointer而是pointed值,所以你必须从Value
"navigate"指向指向变量(结构)的 Value
的指针,这就是 Value.Elem()
的用途。看起来像这样:reflect.ValueOf(&s).Elem()
你可以使用 Value.FieldByName()
方法获取结构字段的 Value
,因为我们将指针的地址传递给 ValueOf()
函数将是 可设置.
代码
代码比介绍简单多了,看懂了。您也可以在 Go Playground:
上尝试var s struct {
A, B, C string
}
s.A, s.B, s.C = "a1", "b2", "c3"
fmt.Println("Before: ", s)
v := reflect.ValueOf(&s).Elem()
v.FieldByName("A").SetString("2a")
v.FieldByName("B").SetString("2b")
v.FieldByName("C").SetString("2c")
fmt.Println("After: ", s)
// Using a map:
m := map[string]string{"A": "ma", "B": "mb", "C": "mc"}
for mk, mv := range m {
v.FieldByName(mk).SetString(mv)
}
fmt.Println("From Map:", s)
输出:
Before: {a1 b2 c3}
After: {2a 2b 2c}
From Map: {ma mb mc}
我建议阅读此博客 post 以了解 Go 中反射的基础知识: