Rufen Sie unabhängig vom Empfängertyp die Methode auf der Schnittstelle {} dynamisch auf
Ich arbeite an einem Templating-System, das in Go geschrieben wurde, was bedeutet, dass es eine liberale Verwendung des erfordertreflect
Paket. In diesem speziellen Fall muss ich in der Lage sein, eine Methode auf einem dynamisch aufzurufeninterface{}
. Die Kuriosität ist, dass meine Reflektionslogik gut funktioniert, solange meine Daten von einem bekannten Typ sind, aber nicht, wenn die Daten vom Typ sindinterface{}
.
Im folgenden Beispiel können Sie sehen, dass die Logik inmain()
undPass()
ist identisch. Der einzige Unterschied besteht darin, ob es sich bei den Daten um einen bekannten Typ oder einen bekannten Typ innerhalb von handeltinterface{}
Geh spielen: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")
}
}
Wenn wir diesen Code ausführen, erhalten wir das folgende Ergebnis
Pass() fail
startfinish
Das bedeutet, dass meine Methode zum dynamischen Aufrufen einer Methode einwandfrei funktioniert, außer in einem Szenario, in dem sich mein Objekt derzeit in einer befindetinterface{}
.
Wenn ich stattdessen keinen Zeigerempfänger benutze und weitergebei
dann funktioniert es wie erwartet.
Geh spielen:http://play.golang.org/p/myM0UXVYzX
Dies lässt mich glauben, dass mein Problem darin besteht, dass ich nicht auf die Adresse von i zugreifen kann (&i
) wenn es eininterface{}
. Ich habe das Reflect-Paket durchsucht und Dinge wie getestetreflect.Value.Addr()
undreflect.PtrTo()
aber ich konnte auch nicht so arbeiten, wie ich es brauchte. Meine Vermutung ist, dass es etwas damit zu tun hat, dass eininterface{}
ist per definitionem ein Referenzobjekt.