如何从接口{}获取结构成员的指针
问题描述:
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..
答
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())
}