Pracuję nad systemem szablonów napisanym w Go, co oznacza, że wymaga on liberalnego użycia pakietu reflect
. W tej konkretnej sytuacji potrzebuję móc dynamicznie wywoływać metodę na interface{}
. Dziwne jest to, że moja logika odbicia działa dobrze, o ile moje dane są znanego typu, ale nie, jeśli dane są typu interface{}
.Dynamicznie wywołaj metodę na interfejsie {} niezależnie od typu odbiornika
W poniższym przykładzie widać, że logika w main()
i Pass()
jest identyczna. Jedyną różnicą jest to, czy dane jest znany typ lub znany typ wewnątrz interface{}
pobaw: 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
Która oznacza, że moja metodologia dynamicznego wywoływania metody działa poprawnie, z wyjątkiem scenariusza, w którym mój obiekt jest aktualnie w postaci interface{}
.
Jeśli zamiast tego nie używam odbiornika wskaźnika i nie przepuszczam i
, to działa zgodnie z oczekiwaniami.
pobaw: http://play.golang.org/p/myM0UXVYzX
To prowadzi mnie do przypuszczenia, że moim problemem jest to, że nie można uzyskać dostępu do adresu I (&i
), gdy jest to interface{}
. Przeszukałem pakiet reflect i przetestowałem takie rzeczy, jak reflect.Value.Addr()
i reflect.PtrTo()
, ale nie mogłem pracować tak, jak potrzebowałem. Mam przeczucie, że ma coś wspólnego z faktem, że interface{}
jest z definicji obiektem referencyjnym.
Dzięki. Chociaż moje pytanie było inne, twoja odpowiedź pomogła mi ustalić, czy struktura ma na niej metodę z 'IsValid()'. – Matt
Wpadłem na to (http://play.golang.org/p/v7lC0swB3s), próbując odpowiedzieć na moje własne pytanie (http://stackoverflow.com/questions/20167935/can-embedded-methods-access-parent pola) – Brenden