通过Go中的反射为struct成员赋值

时间:2015-01-23 17:53:34

标签: dictionary reflection struct 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中的值分配给结构中的相应字段,其中结构和地图定义可能会随着时间的推移而变化,并且地图可能包含更多,或者更少,值比结构。我考虑过用JSON做这件事,但这种做法让我感到有点冷,看到使用反射来获得几乎是多么容易的几乎&#34;有!

谢谢, 肯

1 个答案:

答案 0 :(得分:1)

是的,这是可能的。

<强>简介

由于您要访问和修改变量(或字段)的值,因此需要使用reflect.Value类型而不是reflect.Type。您可以使用reflect.ValueOf()获取它。另外,为了使用反射修改它,您需要传递要修改的struct或值的地址(指针)(否则您只能读取它而不能修改它)。

但是你不想修改地址/指针但是指向值,所以你必须&#34;导航&#34;从指针的Value指向指向变量(struct)的Value,这就是Value.Elem()的用途。它看起来像这样:reflect.ValueOf(&s).Elem()

您可以使用Value.FieldByName()方法获取结构字段的Value,因为我们将指针的地址传递给ValueOf()函数将 settable

守则

一旦你了解它,代码就比引言简单得多。您也可以在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中反射的基础知识:

The Laws of Reflection