mercredi 12 juillet 2017

How to initialize struct pointer via reflection

My goal is to take a nil pointer to a struct (but could be any type), passed as an interface{}, and initialize a struct in its place.

My test code (playground link) is:

package main

import (
    "fmt"
    "reflect"
)

type Foo struct {
    Foo string
}

func main() {
    var x *Foo
    var y interface{} = x
    fmt.Printf("Before: %#v\n", y)
    fmt.Printf("Goal: %#v\n", &Foo{})
    rv := reflect.ValueOf(y)
    for rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Interface {
        fmt.Printf("\t==== %s %s\n", rv.Kind(), rv.Type())
        if rv.Kind() == reflect.Ptr && !rv.Elem().IsValid() {
            rv.Set(reflect.New(rv.Type().Elem()))
        }
        rv = rv.Elem()
    }
    fmt.Printf("\t==== %s \n\n\n\n", rv.Kind())
    fmt.Printf("After: %#v\n", y)
}

I hope the code is self-documenting. But the goal is essentially to convert y ((*main.Foo)(nil)) into &main.Foo{Foo:""}. But I'm getting reflect.Value.Set using unaddressable value. I don't understand why the value I'm attempting to set is unaddressable. I've spent the day reading through the source code to the standard library JSON unmarshaler, and other SO posts, but am still clearly overlooking something.





Aucun commentaire:

Enregistrer un commentaire