【问题标题】:Assign a string to a struct via reflect [duplicate]通过反射将字符串分配给结构
【发布时间】:2021-09-27 07:15:31
【问题描述】:

我有一个结构,我希望使用反射将一个字符串动态更改为另一个字符串。我的问题是新字符串是在堆栈上创建的,因此 Set() 方法会出现恐慌。

这对我来说很有意义,但我不知道如何修复它。我不确定将字符串声明为可寻址的简单方法,或者是否可以使用不同的反射技术。

type MyStruct struct {
    SomeField string
}

func main() {
    myStruct := MyStruct{"initial"}
    hello := "hello world"
    
    field := reflect.ValueOf(myStruct).FieldByName("SomeField")
    helloValue := reflect.ValueOf(hello)
    fmt.Printf("hello is on the stack, canAddr is %v\n", helloValue.CanAddr())
    
    // This will panic because canAddr is false
    field.Set(helloValue)
}

https://play.golang.org/p/ghUgiQfKXhk

【问题讨论】:

  • 您不能制作不可寻址、可寻址的东西(虽然它可能是堆栈分配的,但从语言的角度来看,这与此无关)。但是,您可以使用指向要寻址的值的指针,在这种情况下是 myStruct,而不是 hello

标签: go reflection heap-memory


【解决方案1】:

go 错误有点用词不当。问题在于结构,而不是字符串。

问题出在这一行: field := reflect.ValueOf(myStruct).FieldByName("SomeField") 调用 ValueOf 会传入一个副本(在这种情况下是 myStruct)。由于更改副本不会更改 myStruct,因此出现恐慌(如果隐晦的话,很有帮助)。见【反射第三定律】(https://blog.golang.org/laws-of-reflection#TOC_8)

将此行更改为field := reflect.ValueOf(&myStruct).Elem().FieldByName("SomeField") 可修复错误(注意 & 获取地址,然后 Elem() 取消引用)

当然,我只是在发布问题后才知道这一点,但希望它会对其他人有所帮助

【讨论】:

    猜你喜欢
    • 2012-05-08
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 2021-04-29
    • 2017-06-12
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    相关资源
    最近更新 更多