使用reflection,你如何设置一个struct字段的值?
有一个艰难的时间使用reflect
包使用struct字段。 特别是还没有想出如何设置字段值。
键入t struct {fi int; fs string} var rt = t {123,“jblow”} var i64 int64 = 456
-
得到领域的名字我 – 这似乎工作
var field = reflect.TypeOf(r).Field(i).Name
-
获得领域我的价值作为一个)interface {},b)int – 这似乎工作
var iface interface{} = reflect.ValueOf(r).Field(i).Interface()
var i int = int(reflect.ValueOf(r).Field(i).Int())
-
设置领域的价值 – 尝试一个恐慌
reflect.ValueOf(r).Field(i).SetInt( i64 )
恐慌 :reflect.Value·SetInt使用取得的值使用未导出的字段
假设它不喜欢字段名称“id”和“name”,所以改名为“Id”和“Name”
a)这个假设是否正确?
b)如果正确,认为没有必要,因为在相同的文件/包
-
设置字段i的值 – 尝试两个(字段名称大写) – 恐慌
reflect.ValueOf(r).Field(i).SetInt( 465 )
reflect.ValueOf(r).Field(i).SetInt( i64 )
恐慌 :reflect.Value·SetInt使用unaddressable值
以下说明@peterSO是彻底的,高质量
四。 这工作:
reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )
他还logging了域名必须是可导出的(以大写字母开头)
Go以开源代码的forms提供 。 了解反思的一个好方法是看看核心Go开发人员如何使用它。 例如,Go fmt和json软件包。 软件包文档包含指向软件包文件标题下的源代码文件的链接。
Go json包封送和解组JSON来自Go结构。
这是一个循序渐进的例子,它可以设置一个struct
字段的值,同时小心避免错误。
Go reflect
包有一个CanAddr
函数。
func (v Value) CanAddr() bool
如果可以使用Addr获取值的地址,则CanAddr返回true。 这些值被称为可寻址的。 如果值是切片的元素,可寻址数组的元素,可寻址结构的字段或解引用指针的结果,则该值是可寻址的。 如果CanAddr返回false,调用Addr将会发生混乱。
Go reflect
包有一个CanSet
函数,如果为true
,则暗示CanAddr
也是true
。
func (v Value) CanSet() bool
如果v的值可以改变,CanSet返回true。 值只有在可寻址的情况下才能被改变,并且不能通过使用未导出的结构字段来获得。 如果CanSet返回false,则调用Set或任何types特定的setter(例如,SetBool,SetInt64)将会发生混乱。
我们需要确保我们可以Set
struct
字段。 例如,
package main import ( "fmt" "reflect" ) func main() { type t struct { N int } var n = t{42} // N at start fmt.Println(nN) // pointer to struct - addressable ps := reflect.ValueOf(&n) // struct s := ps.Elem() if s.Kind() == reflect.Struct { // exported field f := s.FieldByName("N") if f.IsValid() { // A Value can be changed only if it is // addressable and was not obtained by // the use of unexported struct fields. if f.CanSet() { // change value of N if f.Kind() == reflect.Int { x := int64(7) if !f.OverflowInt(x) { f.SetInt(x) } } } } } // N at end fmt.Println(nN) } Output: 42 7
如果我们可以确定所有的错误检查是不必要的,那么这个例子简化为:
package main import ( "fmt" "reflect" ) func main() { type t struct { N int } var n = t{42} fmt.Println(nN) reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7) fmt.Println(nN) }
这似乎工作:
package main import ( "fmt" "reflect" ) type Foo struct { Number int Text string } func main() { foo := Foo{123, "Hello"} fmt.Println(int(reflect.ValueOf(foo).Field(0).Int())) reflect.ValueOf(&foo).Elem().Field(0).SetInt(321) fmt.Println(int(reflect.ValueOf(foo).Field(0).Int())) }
打印:
123 321