Llamar dinámicamente al método en la interfaz {} independientemente del tipo de receptor
Estoy trabajando en un sistema de plantillas escrito en Go, lo que significa que requiere un uso liberal de lareflect
paquete. En esta circunstancia específica necesito poder llamar dinámicamente un método en uninterface{}
. La rareza es que mi lógica de reflexión funciona bien siempre que mis datos sean de un tipo conocido, pero no si los datos son de tipointerface{}
.
El siguiente ejemplo puede ver que la lógica enmain()
yPass()
es idéntico. La única diferencia es si los datos son un tipo conocido o un tipo conocido dentro de uninterface{}
Ir a jugar:http://play.golang.org/p/FTP3wgc0sZ
package main
import (
"fmt"
"reflect"
)
type Test struct {
Start string
}
func (t *Test) Finish() string {
return t.Start + "finish"
}
func Pass(i interface{}) {
_, ok := reflect.TypeOf(&i).MethodByName("Finish")
if ok {
fmt.Println(reflect.ValueOf(&i).MethodByName("Finish").Call([]reflect.Value{})[0])
} else {
fmt.Println("Pass() fail")
}
}
func main() {
i := Test{Start: "start"}
Pass(i)
_, ok := reflect.TypeOf(&i).MethodByName("Finish")
if ok {
fmt.Println(reflect.ValueOf(&i).MethodByName("Finish").Call([]reflect.Value{})[0])
} else {
fmt.Println("main() fail")
}
}
Al ejecutar este código obtenemos el siguiente resultado
Pass() fail
startfinish
Lo que significa que mi metodología para llamar dinámicamente a un método funciona bien, excepto en un escenario cuando mi objeto se encuentra actualmente en uninterface{}
.
Si por el contrario no uso un receptor de puntero y pasei
entonces funciona como se espera.
Ir a jugar:http://play.golang.org/p/myM0UXVYzX
Esto me lleva a creer que mi problema es que no puedo acceder a la dirección de i (&i
) cuando es uninterface{}
. He rastreado el paquete reflectante y he probado cosas comoreflect.Value.Addr()
yreflect.PtrTo()
Pero tampoco pude llegar a trabajar como yo necesitaba. Mi corazonada es que tiene algo que ver con el hecho de que unainterface{}
Es por definición un objeto de referencia.