指针 – Golang反射:无法设置包含结构体的界面的字段

前端之家收集整理的这篇文章主要介绍了指针 – Golang反射:无法设置包含结构体的界面的字段前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图实现一个方法来改变可以具有任意结构的对象中的字段的值.当我有一个指向一个结构体的指针时,字段的转换就没有问题.但是当我有一个接口不包含指向结构体的指针但结构本身时,我无法设法更改这些字段:简而言之
// 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

我已经阅读了The Laws of Reflection,所以我知道,当我有一个指向结构体的指针时,我只能修改字段.所以我的问题现在是:如何获取指向结构数据的指针?

更新:

我使用基本上y:= reflect.New(reflect.TypeOf(x))使它工作,所以y的值现在可以设置.有关广泛的示例,请参阅:https://gist.github.com/hvoecking/10772475

您似乎试图修改存储在接口变量中的动态值.您可以在接口变量上执行的唯一操作是获取或设置动态值(复制操作),并检查存储值的类型.

为了理解为什么这样做,想象有一个这样的操作,我们有以下代码

var ptr *A = pointer_to_dynamic_value(x)
x = B{...}

ptr现在代表什么?当向接口变量分配新值时,该语言可以自由地重用存储,因此ptr现在可以指向B值的内存,这会破坏语言的类型安全性(目前的编译器存储仅保证为重复使用小价值,但依然存在).

将存储在界面中的值进行变异的唯一安全方式是将值复制出来,然后分配修改后的版本.例如:

a := x.(A)
a.Str = "Bye"
x = a

反射包反映了这些限制,因此表示动态值字段的reflect.Value被认为是只读的.

您可以在第一个示例中设置字段,因为z的动态值是* A指针而不是struct本身:这意味着可以修改引用的结构体.

猜你在找的Go相关文章