Ho trovato una funzione chiamata MethodByName()
qui http://golang.org/pkg/reflect/#Value.MethodByName ma non è esattamente quello che voglio! (forse perché non so come usarlo … non riesco a trovare alcun esempio con esso). Quello che voglio è:
type MyStruct struct { //some feilds here } func (p *MyStruct) MyMethod { println("My statement."); } CallFunc("MyStruct", "MyMethod"); //print out My statement."
Quindi, suppongo, prima ho bisogno di qualcosa come StructByName()
e dopo che lo uso per MethodByName()
, è giusto ?!
Per chiamare un metodo su un object, utilizzare prima reflect.ValueOf
. Quindi trova il metodo in base al nome e infine chiama il metodo trovato. Per esempio:
package main import "fmt" import "reflect" type T struct {} func (t *T) Foo() { fmt.Println("foo") } func main() { var t T reflect.ValueOf(&t).MethodByName("Foo").Call([]reflect.Value{}) }
type YourT1 struct {} func (y YourT1) MethodBar() { //do something } type YourT2 struct {} func (y YourT2) MethodFoo(i int, oo string) { //do something } func Invoke(any interface{}, name string, args... interface{}) { inputs := make([]reflect.Value, len(args)) for i, _ := range args { inputs[i] = reflect.ValueOf(args[i]) } reflect.ValueOf(any).MethodByName(name).Call(inputs) } func main() { Invoke(YourT2{}, "MethodFoo", 10, "abc") Invoke(YourT1{}, "MethodBar") }
In realtà, è necessario che il codice verifichi validamente il numero di input del metodo o il metodo stesso. È ansible fare riferimento a questo http://gowalker.org/reflect#Type
ret
da reflect.Value.Interface()
e stai attento al tipo Ptr; oppure Puoi usare SomeInterface{}
invece di usare direttamente l’ interface{}
per assicurare questo tipo “qualsiasi”, come questo
type Shape interface { Area() float64 //some method to ensure any is an Shape type. } func Invoke(s Shape, name string, inputs...interface{}) []interface{} { }
quindi questo è OK
color := Invoke(Circle{}, "GetColor")[0].(Color)
ma
Invoke(NotAnShape{}, "ForBar")
non può essere compilato perché NotAnShape
non è una forma.
Se non sei sicuro di quale sarà il primo tipo utilizzato in fase di compilazione, puoi build una mappa per memorizzare tutti i tipi possibili, come questo.
map[string]reflect.Value{ "YourT1" : reflect.ValueOf(YourT1{}) "YourT2" : reflect.ValueOf(YourT2{}) "Circle" : reflect.ValueOf(Cirlce{}) // or reflect.ValueOf(&Circle{}) }