mercredi 5 avril 2017

How can I covert struct value into struct pointer using reflection

Suppose that I have the following types, the following snippets mimic production code:

import (
    "reflect"
)

type IFace interface {
    A() 
    B()
    C()
}

type Meta struct {
    s string
}

func (m *Meta) A() {}
func (m *Meta) B() {}
func (m *Meta) C() {}

type One struct {
    M *Meta
    B bool
}

func (o *One) A() {}
func (o *One) B() {}
func (o *One) C() {}

And I have a method that does the following:

func Alias(src, dest *Meta) (IFace, error) {
    base, err := find(src) //asume that `find` is implemented and err is nil
    if err != nil { 
       return err
    }

    // trouble starts here ...
    // allocate new "instance"
    aliased := reflect.New(reflect.TypeOf(base)).Elem().Interface()

    // copy the base value
    aliased = base 

    aliasedV := reflect.ValueOf(aliased).Elem()
    fm := aliasedV.FieldByName("M")
    fm.Set(reflect.ValueOf(dest))

    return aliasedV.Interface().(Iface), nil
}

It compiles and runs however with the following TestFunction it gives me this error message:

interface conversion: One is not IFace: missing method C [recovered]
    panic: interface conversion: One is not IFace: missing method C

and the test function:

func TestOne(t *testing.T) {
   srcID := &Meta{S: "SRC"}
   destID := &Meta{S: "DEST"}
   aliased, err := Alias(srcID, destID)
   if err != nil {
       t.Error(err)
   }

   one, isOne := aliased.(*One)
   if !isOne {
       t.Error("fail")
   }
}

Is there a way to have an interface{} type that wraps a struct value become an interface{} type that wraps a struct pointer without using the underlying struct type directly, like avoiding: var any interface{} = aliased.(*One) ??,

Could the unsafe package be of help here?





Aucun commentaire:

Enregistrer un commentaire