英文:
set variable of any struct passed as interface{}
问题
我想知道如何在使用interface{}
值时使用反射设置变量,并且可以传递各种结构体到func F(o interface{})
。如何将第一个值(s.A)更改为'hello'?
package main
import (
"fmt"
"reflect"
)
type T struct {
A string
}
func main() {
F(T{"foo"})
}
func F(o interface{}) {
t := reflect.ValueOf(&T{"bar"}).Elem()
s := reflect.ValueOf(&o).Elem()
// ok
fmt.Println("struct: ", t.Field(0).CanSet())
// panics - how to set s.A?
fmt.Println("interface:", s.Field(0).CanSet())
}
你可以使用reflect.Value
的FieldByName
方法来设置变量的值。在这种情况下,你可以使用FieldByName
方法来获取字段的值,并使用SetValue
方法来设置新的值。以下是修改后的代码:
package main
import (
"fmt"
"reflect"
)
type T struct {
A string
}
func main() {
F(T{"foo"})
}
func F(o interface{}) {
t := reflect.ValueOf(&T{"bar"}).Elem()
s := reflect.ValueOf(&o).Elem()
// ok
fmt.Println("struct: ", t.Field(0).CanSet())
// set s.A
field := s.FieldByName("A")
if field.IsValid() && field.CanSet() {
field.SetString("hello")
}
fmt.Println("interface:", s.Field(0).CanSet())
fmt.Println("s.A:", s.Field(0).Interface())
}
这样,你就可以将s.A
的值更改为'hello'了。
英文:
I would like to know how to set a variable using reflection when using an interface{}
value, and all kind of structs could be passed to func F(o interface{})
. How to change the first value (s.A) to 'hello'?
package main
import (
"fmt"
"reflect"
)
type T struct {
A string
}
func main() {
F(T{"foo"})
}
func F(o interface{}) {
t := reflect.ValueOf(&T{"bar"}).Elem()
s := reflect.ValueOf(&o).Elem()
// ok
fmt.Println("struct: ", t.Field(0).CanSet())
// panics - how to set s.A?
fmt.Println("interface:", s.Field(0).CanSet())
}
答案1
得分: 1
请参考以下链接:http://play.golang.org/p/F6M5mfMOTY
当你将引用值&o
传递给reflect.ValueOf
时,Go语言将Elem()
解释为interface{}
,而不是你原始的类型。如果你不传递引用,你将得到一个(不可寻址的)实例。我不能百分之百确定为什么会这样,但你可以在上面的链接中看到这种行为。
一种方法是创建一个新的可寻址实例,并遍历s
返回的值,在新实例中设置字段,然后返回它。
英文:
See http://play.golang.org/p/F6M5mfMOTY
When you pass the reference value &o
, to reflect.ValueOf
, Go is interpreting the Elem()
as interface{}
, not your original type. If you don't pass as a reference, you get a (non-addressable) instance of your type. I am not 100% sure why this is, but you can definitely see the behavior at the play link above.
One approach would be to create a new addressable instance of your type, and then iterate over the value returned by s
to set the fields in the new instance and then return it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论