在Go中使用反射设置表示nil指针的接口的值



我的问题类似于如何通过反射初始化结构指针。

我有一个表示零指针的接口。我想更新nil指针后面的值。

我从上面提到的问题的答案中的一个例子中获取了代码,但我的情况略有不同,并且给定的解决方案不起作用。

InitNilPointer()内部,该值实际上变为&Foo{}。但是在呼叫站点的结果仍然是(*Foo)(nil)。如何使用反射将main()中的foo更新为&Foo{}

情况如下

func main() {
var foo *Foo
InitNilPointer(foo)
// Want: &main.Foo{A:""}
fmt.Printf("Want: %+#vn", &Foo{})
// Got: (*main.Foo)(nil)
fmt.Printf("Got: %+#vn", foo)
}
// InitNilPointer initiates the given pointer to a nil value to become a pointer to 
// a value. E.g. (*Foo)(nil) becomes &Foo{}.
func InitNilPointer(source interface{}) {
v := reflect.ValueOf(source)
if reflect.Indirect(v).IsValid() {
return
}
rv := reflect.ValueOf(&source).Elem()
t := rv.Elem().Type().Elem()
// This only updates the value locally. The call site still has a nil pointer. SAD.
rv.Set(reflect.New(t))
// source: &main.Foo{A:""}
fmt.Printf("source: %+#vn", source)
}

无论传递给函数什么,都会生成一个副本。如果传递foo,无论函数做什么,它都只能修改副本,而不能修改原始foo变量。

因此,必须通过&foo(修改指向的对象将修改foo(:

func main() {
var foo *Foo
InitNilPointer(&foo)
fmt.Printf("Want: %+#vn", &Foo{})
fmt.Printf("Got: %+#vn", foo)
}
func InitNilPointer(source interface{}) {
rv := reflect.ValueOf(source).Elem()
if reflect.Indirect(rv).IsValid() {
return
}
t := rv.Type().Elem()
rv.Set(reflect.New(t))
// source: &main.Foo{A:""}
fmt.Printf("source: %+#vn", source)
}

这将输出(在Go Playground上尝试(:

source: (**main.Foo)(0xc00000e028)
Want: &main.Foo{A:""}
Got: &main.Foo{A:""}

相关内容

  • 没有找到相关文章

最新更新