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
}
playground example
The conversion to integer pointer goes as follows:
v
is a reflect.Value
representing the int
field.v.Addr()
is a relfect.Value
representing a pointer to the int
field.v.Addr().Interface()
is an interface{}
containing the int
pointer.v.Addr().Interface().(*int)
type asserts the interface{}
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)
}
playground example
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())
}
playground example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With