How to get a pointer to a member of a structure from the {} interface

I want to pass a struct pointer to a function that expects an interface {}. Then place (through reflection) the pointer on the structure element, and then change it using this pointer. I read a lot of questions and tried many options, but still I can get it to work.

Consider the 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 is a poor understanding of what the Addr () and Pointer () methods actually do to reflect the package.

+6
source share
1 answer

Here's the working version of f:

 func f(i interface{}) { v := reflect.ValueOf(i).Elem().FieldByName("Id") ptr := v.Addr().Interface().(*int) *ptr = 100 } 

playground example

The conversion to an integer pointer is as follows:

  • v is reflect.Value representing the int field.
  • v.Addr() is a relfect.Value representing a pointer to an int field.
  • v.Addr().Interface() is an interface{} containing an int pointer.
  • v.Addr().Interface().(*int) type asserts interface{} on *int

You can set the field directly without specifying a pointer:

 func f(i interface{}) { v := reflect.ValueOf(i).Elem().FieldByName("Id") v.SetInt(100) } 

playground example

If you pass a value while waiting for the {} interface (for example, db / sql Scan methods), you can remove the statement like:

 func f(i interface{}) { v := reflect.ValueOf(i).Elem().FieldByName("Id") scan(v.Addr().Interface()) } 

playground example

+19
source

Source: https://habr.com/ru/post/981130/


All Articles