我正在尝试实现一种方法,该方法可以更改可以具有任意结构的对象中的字段值。当我有指向结构的指针时,字段的遍历没有问题。但是,当我有一个接口不包装指向结构的指针而是包装结构本身时,我无法设法更改字段,简而言之:
// The following doesn't work
var x interface{} = A{Str: "Hello"}
// This panics: reflect: call of reflect.Value.Field on ptr Value
reflect.ValueOf(&x).Field(0).SetString("Bye")
// This panics: reflect: call of reflect.Value.Field on interface Value
reflect.ValueOf(&x).Elem().Field(0).SetString("Bye")
// This panics: reflect: reflect.Value.SetString using unaddressable value
reflect.ValueOf(&x).Elem().Elem().Field(0).SetString("Bye")
// This prints `false`. But I want this to be settable
fmt.Println(reflect.ValueOf(&x).Elem().Elem().Field(0).CanSet())
// This works
var z interface{} = &A{Str: "Hello"}
// This prints `true`
fmt.Println(reflect.ValueOf(z).Elem().Field(0).CanSet())
长:http://play.golang.org/p/OsnCPvOx8F http://play.golang.org/p/OsnCPvOx8F
我读过了反思法则 http://blog.golang.org/laws-of-reflection所以我知道只有当我有指向结构的指针时才可以修改字段。所以我现在的问题是:如何获取指向结构体数据的指针?
UPDATE:
我基本上使用它来工作y := reflect.New(reflect.TypeOf(x))
所以值y
现在可以设置了。有关详细示例,请参阅:https://gist.github.com/hvoecking/10772475 https://gist.github.com/hvoecking/10772475
您似乎正在尝试修改存储在接口变量内的动态值。您可以对接口变量执行的唯一操作是获取或设置动态值(进行复制的操作)以及检查存储值的类型。
要理解为什么事情会这样,想象一下有这样一个操作,并且我们有以下代码:
var ptr *A = pointer_to_dynamic_value(x)
x = B{...}
什么是ptr
现在代表?当为接口变量分配新值时,该语言可以自由地重用存储,因此ptr
现在可能指向内存B
value,这破坏了语言的类型安全(当前编译器的存储只能保证可以重用小值,但这一点仍然存在)。
改变接口中存储的值的唯一安全方法是将值复制出来,然后分配回修改后的版本。例如:
a := x.(A)
a.Str = "Bye"
x = a
The reflect
包反映了这些限制,所以reflect.Value
表示动态值的字段被视为只读。
您可以在第一个示例中设置字段,因为动态值z
is a *A
指针而不是结构本身:这意味着可以修改引用的结构。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)