Get pointer to value using reflection

Mihai H :

I have a function that iterates through all fields of an interface passed as parameter. In order to achieve this is I am using reflection. The issue is that I do not know how to obtain the address of a non-pointer field. Here is an example:

type Z struct {
    Id int
}

type V struct {
    Id int
    F Z
}

type T struct {
    Id int
    F V
}

The above code represents my test structures. Now here is the actual function which traverses a specified structure and lists details about it:

func InspectStruct(o interface{}) {
     val := reflect.ValueOf(o)
     if val.Kind() == reflect.Interface && !val.IsNil() {
        elm := val.Elem()
        if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
            val = elm
        }
     }
     if val.Kind() == reflect.Ptr {
        val = val.Elem()
     }

    for i := 0; i < val.NumField(); i++ {
        valueField := val.Field(i)
        typeField := val.Type().Field(i)
        address := "not-addressable"

        if valueField.Kind() == reflect.Interface && !valueField.IsNil() {
            elm := valueField.Elem()
            if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
                valueField = elm
            }
        }
        if valueField.Kind() == reflect.Ptr {
            valueField = valueField.Elem()
        }
        if valueField.CanAddr() {
            address = fmt.Sprint(valueField.Addr().Pointer())
        }

        fmt.Printf("Field Name: %s,\t Field Value: %v,\t Address: %v\t, Field type: %v\t, Field kind: %v\n", typeField.Name, 
            valueField.Interface(), address, typeField.Type, valueField.Kind())

        if valueField.Kind() == reflect.Struct {
            InspectStruct(valueField.Interface())
        }
    }
}

And here is the actual test after structure instantiation/initialization:

t := new(T)
t.Id = 1
t.F = *new(V)
t.F.Id = 2
t.F.F = *new(Z)
t.F.F.Id = 3

InspectStruct(t)

And finally the output of InspectStruct call:

Field Name: Id,  Field Value: 1,     Address: 408125440 , Field type: int   , Field kind: int
Field Name: F,   Field Value: {2 {3}},   Address: 408125444 , Field type: main.V    , Field kind: struct
Field Name: Id,  Field Value: 2,     Address: not-addressable   , Field type: int   , Field kind: int
Field Name: F,   Field Value: {3},   Address: not-addressable   , Field type: main.Z    , Field kind: struct
Field Name: Id,  Field Value: 3,     Address: not-addressable   , Field type: int   , Field kind: int

As you can see I am using recursion, so if one of the fields is a struct kind then I call InspectStruct for it. My issue is that though all fields have been initialized for the entire structure "t" hierarchy, I am not able to get the address for any field located at a higher depth than "t". I would really appreciate any help.

OneOfOne :

Passing reflect.Value instead of interface{} seems to fix the problem, however I don't know why valueField.Interface() doesn't work.

Working example : http://play.golang.org/p/nleA2YWMj8

func InspectStructV(val reflect.Value) {
    if val.Kind() == reflect.Interface && !val.IsNil() {
        elm := val.Elem()
        if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
            val = elm
        }
    }
    if val.Kind() == reflect.Ptr {
        val = val.Elem()
    }

    for i := 0; i < val.NumField(); i++ {
        valueField := val.Field(i)
        typeField := val.Type().Field(i)
        address := "not-addressable"

        if valueField.Kind() == reflect.Interface && !valueField.IsNil() {
            elm := valueField.Elem()
            if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
                valueField = elm
            }
        }

        if valueField.Kind() == reflect.Ptr {
            valueField = valueField.Elem()

        }
        if valueField.CanAddr() {
            address = fmt.Sprintf("0x%X", valueField.Addr().Pointer())
        }

        fmt.Printf("Field Name: %s,\t Field Value: %v,\t Address: %v\t, Field type: %v\t, Field kind: %v\n", typeField.Name,
            valueField.Interface(), address, typeField.Type, valueField.Kind())

        if valueField.Kind() == reflect.Struct {
            InspectStructV(valueField)
        }
    }
}

func InspectStruct(v interface{}) {
    InspectStructV(reflect.ValueOf(v))
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How do you set a value to a pointer containing nil using reflection

How can I convert struct value into struct pointer using reflection

Is it possible to extract the value of an interface from a pointer to the interface using reflection?

How to get class in the field value using reflection?

Get property value from string using reflection

Get value from resource using Reflection

Using Reflection get value of the field on c#

How to get the value of associate field using reflection

How to get variable name of string pointer by using reflection?

Set a pointer to a field using reflection

Using pointer in function to get value from the input

Get value of enum by reflection

How to get default value of auto property in C# using reflection?

Get value of static field using reflection in kotlin for generic type

Get protected property value of base class using reflection

How to get source value affected to a constant using C# reflection

How to get last value from an ArrayList using reflection?

Acumatica Customization: Can I get value of fields in Cache using reflection?

Which is the most optimal way to get or set the value of a property using reflection

Changing pointer type and value under interface with reflection

Get annotation value via reflection

Reflection to get default value of parameter

Reflection generic get field value

Get Enum value by reflection in Kotlin

Java reflection - get field value

Get value from pointer

Get the value of a Cython pointer

Setting a value into a object using reflection

Getting the value of a tuple using reflection