英文:
Assign a string to a struct via reflect
问题
我有一个结构体,在其中我希望使用反射动态地将一个字符串更改为另一个字符串。我的问题是新字符串是在堆栈上创建的,因此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())
// 这将引发恐慌,因为canAddr为false
field.Set(helloValue)
}
https://play.golang.org/p/ghUgiQfKXhk
英文:
I have a struct, where I wish to dynamically change a string to another string using reflect. My issue is that the new string is created on the stack, and therefore the Set() method panics.
This makes sense to me, but I don't know how to fix it. I'm not sure the easy way to declare a string as addressable or if there's a different reflection technique to use.
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)
}
答案1
得分: 2
go错误有点误导人。问题出在结构体上,而不是字符串。
问题出在这一行:
field := reflect.ValueOf(myStruct).FieldByName("SomeField")
调用ValueOf
传入了一个副本(在这种情况下是myStruct的副本)。由于更改副本不会更改myStruct,所以go会发生恐慌(虽然有帮助,但有点晦涩)。参见反射的第三定律。
将这一行更改为field := reflect.ValueOf(&myStruct).Elem().FieldByName("SomeField")
可以修复错误(注意使用&
获取地址,然后使用Elem()
解引用)。
当然,我在发布问题后才弄清楚这一点,但希望能帮助其他人。
英文:
The go error is a bit of a misnomer. The problem is with the struct, not the string.
The problem is in this line:
field := reflect.ValueOf(myStruct).FieldByName("SomeField")
Calling ValueOf
passes in a copy (of myStruct in this case). Since changing a copy won't change myStruct, then go panics (helpfully, if cryptically). See [the third law of reflection] (https://blog.golang.org/laws-of-reflection#TOC_8)
Changing this line to field := reflect.ValueOf(&myStruct).Elem().FieldByName("SomeField")
fixes the error (note the & to take the address, and then Elem() to dereference)
Of course I only figure this out after posting the question but hopefully it will help someone else
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论