我有一个带有成员A,B,C字符串的struct 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"
但这显然行不通。如果仅知道字段名称,是否可以将值分配给结构?
在实践中,我试图将来自a的值分配给map[string]string结构中的相应字段,其中结构和映射定义可能会随着时间的变化而扩展,并且映射可能包含比该结构更多或更少的值。我已经考虑过使用JSON进行此操作,但是这种方法让我有些不高兴,因为使用反射来“几乎”到达那里是多么容易!
map[string]string
谢谢,肯
是的,有可能。
介绍
由于您要访问和修改变量(或字段)的值,因此需要使用reflect.Value类型而不是reflect.Type。您可以使用获取它reflect.ValueOf()。同样,为了通过反射进行修改,您需要传递struct要修改的或值的地址(指针)(否则,您只能读取它,而不能修改它)。
reflect.Value
reflect.Type
reflect.ValueOf()
struct
但你不希望修改地址/指针,但 尖锐的 价值,所以你必须从“导航” Value的指针的Value尖头变量(结构),这是什么Value.Elem()是。看起来像这样:reflect.ValueOf(&s).Elem()
Value
Value.Elem()
reflect.ValueOf(&s).Elem()
您可以使用方法获得Valuestruct字段的Value.FieldByName(),因为我们传递了指向ValueOf()函数的指针的地址,所以它是 可设置的 。
Value.FieldByName()
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}
我建议阅读此博客文章,以了解Go语言中反射的基础知识:
反射定律