英文:
How get pointer of struct's member from interface{}
问题
我想将结构体的指针传递给期望接口{}的函数,然后通过反射获取结构体成员的指针,并使用该指针进行修改。我已经阅读了很多问答并尝试了很多变化,但仍然无法使其工作。
让我们考虑下面的示例:
type Robot struct {
Id int
}
f := func(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
ptr := v.Addr().Pointer()
*ptr = 100
//^ 这对于期望指针的函数是必需的:Scan(&pointerToValue)
}
robot := &Robot{}
f(robot)
println(robot.Id) //我希望在这里得到100
我认为问题在于对反射包的**Addr()和Pointer()**方法的理解不够清楚。
英文:
I want to pass struct's pointer to function that expect interface{}. Then get (through reflection) the pointer to the struct's member and then modify it using this pointer. I've read a much of Q&A and tried much of variations, but still I can get it work.
Let's consider example below:
type Robot struct {
Id int
}
f := func(i interface {}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
ptr := v.Addr().Pointer()
*ptr = 100
//^ it needs to me for functions expecting the pointer: Scan(&pointerToValue)
}
robot := &Robot{}
f(robot)
println(robot.Id) //I want to get here 100
I think the problem in poor understanding what actually do Addr() and Pointer() methods of reflect package..
答案1
得分: 21
这是函数f的一个可工作版本:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
ptr := v.Addr().Interface().(*int)
*ptr = 100
}
将整数转换为指针的过程如下:
v
是表示int
字段的reflect.Value
。v.Addr()
是表示int
字段的指针的reflect.Value
。v.Addr().Interface()
是包含int
指针的interface{}
。v.Addr().Interface().(*int)
类型断言 将interface{}
断言为*int
。
你可以直接设置字段而不获取指针:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
v.SetInt(100)
}
如果你将值传递给期望interface{}
的某些东西(比如db/sql的Scan方法),那么你可以去除类型断言:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
scan(v.Addr().Interface())
}
英文:
Here's a working version of function f:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
ptr := v.Addr().Interface().(*int)
*ptr = 100
}
The conversion to integer pointer goes as follows:
v
is areflect.Value
representing theint
field.v.Addr()
is arelfect.Value
representing a pointer to theint
field.v.Addr().Interface()
is aninterface{}
containing theint
pointer.v.Addr().Interface().(*int)
type asserts theinterface{}
to a*int
You can set the field directly without getting a pointer:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
v.SetInt(100)
}
If you are passing the value along to something expecting interface{} (like the db/sql Scan methods), then you can remove the type assertion:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
scan(v.Addr().Interface())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论