繁体   English   中英

如何通过反射初始化结构指针

[英]How to initialize struct pointer via reflection

我的目标是采用一个指向结构的nil指针(但可以是任何类型),作为interface{}传递,并在其位置初始化一个结构。

我的测试代码( 游乐场链接 )是:

package main

import (
    "fmt"
    "reflect"
)

type Foo struct {
    Foo string
}

func main() {
    var x *Foo
    var y interface{} = x
    fmt.Printf("Before: %#v\n", y)
    fmt.Printf("Goal: %#v\n", interface{}(&Foo{}))

    rv := reflect.ValueOf(y)
    rv.Set(reflect.New(rv.Type().Elem()))

    fmt.Printf("After: %#v\n", y)
}

我希望代码能自我记录。 但目标是基本上转换y其开始作为一个未初始化的指针Foo ,( (*main.Foo)(nil) )插入的指针初始化(零值)的实例Foo&main.Foo{Foo:""} 但是我正在reflect.Value.Set using unaddressable value获取reflect.Value.Set using unaddressable value 我不明白为什么我要设置的值无法寻址。 我花了整整一天的时间阅读标准库JSON unmarshaler的源代码以及其他SO帖子,但仍然明显忽略了一些内容。

如果我剥掉外部interface{}

rv := reflect.ValueOf(y).Elem() // Remove the outer interface{}
rv.Set(reflect.New(rv.Type().Elem()))

错误变为reflect: call of reflect.Value.Type on zero Value

尝试这个:

var x *Foo
var y interface{} = x
fmt.Printf("Before: %#v\n", y)
fmt.Printf("Goal: %#v\n", interface{}(&Foo{}))

// Must take address of y to set it. Dereference with Elem() to get value for y
rv := reflect.ValueOf(&y).Elem()

// Interface element type is *main.Foo, dereference with Elem() to get main.Foo
t := rv.Elem().Type().Elem()
rv.Set(reflect.New(t))
fmt.Printf("After: %#v\n", y)

游乐场的例子

您还可以分配y而不是通过反射进行设置:

var x *Foo
var y interface{} = x
fmt.Printf("Before: %#v\n", y)
fmt.Printf("Goal: %#v\n", interface{}(&Foo{}))
rv := reflect.ValueOf(y)
t := rv.Type().Elem()
y = reflect.New(t).Interface()
fmt.Printf("After: %#v\n", y)

游乐场的例子

在您的示例中rv.CanAddr()false ,因此您无法设置它( rv.CanSet()false )。

问题:如果您有一个指向nil的指针,则该指针不可寻址。 但是,指向nil的指针(或指向接口的指针)的指针是可寻址的。

您可以使示例以不同的方式工作:

  • 将x初始化为非零(可能不是这里的要点)
  • 使用reflect.New(..)将y设置为新值

     func main() { var x *Foo var y interface{} = x fmt.Printf("Before: %#v\\n", y) fmt.Printf("Goal: %#v\\n", interface{}(&Foo{})) rv := reflect.ValueOf(y) y = reflect.New(rv.Type().Elem()).Interface() fmt.Printf("After: %#v\\n", y) } 

不知道您的实际使用情况下,很难说什么你需要的解决方案,但是这个工程为您的示例:

var x *Foo
var y interface{} = x
rv := reflect.ValueOf(y)
y = reflect.New(rv.Type().Elem()).Interface()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM