Dynamicznie wywołaj metodę na interfejsie {} niezależnie od typu odbiorcy
Pracuję nad systemem szablonów napisanym w Go, co oznacza, że wymaga on swobodnego używaniareflect
pakiet. W tej konkretnej sytuacji muszę być w stanie dynamicznie wywołać metodę nainterface{}
. Dziwne jest to, że moja logika refleksji działa dobrze, dopóki moje dane są znanego typu, ale nie, jeśli dane są typuinterface{}
.
W poniższym przykładzie widać, że logika wmain()
iPass()
jest identyczny. Jedyną różnicą jest to, czy dane są znanym typem, czy znanym typem wewnątrzinterface{}
CHodźmy grać: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")
}
}
Po wykonaniu tego kodu otrzymujemy następujący wynik
Pass() fail
startfinish
Oznacza to, że moja metodologia dynamicznego wywoływania metody działa dobrze, z wyjątkiem scenariusza, w którym mój obiekt jest obecnie w trybieinterface{}
.
Jeśli zamiast tego nie używam odbiornika wskaźnika i przekazujęi
to działa zgodnie z oczekiwaniami.
CHodźmy grać:http://play.golang.org/p/myM0UXVYzX
To prowadzi mnie do przekonania, że moim problemem jest to, że nie mogę uzyskać dostępu do adresu i (&i
) kiedy to jestinterface{}
. Przeszukałem pakiet i sprawdziłem takie rzeczy, jakreflect.Value.Addr()
ireflect.PtrTo()
ale nie mogłem ani pracować tak, jak potrzebowałem. Moje przeczucie jest takie, że ma to coś wspólnego z faktem, żeinterface{}
jest z definicji obiektem odniesienia.