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")
}
実際、コードはメソッドの入力番号をチェックする必要があり、メソッド自体が存在するかどうかさえもチェックする必要があります。
このhttp://gowalker.org/reflect#Typeを参照できます
- 「any」が構造体タイプであることを確認してください
- 「any」に「name」メソッドがあることを確認してください
- メソッド「name」の入力パラメーターの数がargsの長さと等しいことを確認してください
- によって実装
ret
するreflect.Value.Interface()
Ptrタイプに注意してください。
またはSomeInterface{}
、直接使用する代わりに、次のinterface{}
ようにこの「任意の」タイプを確保するために使用できます。
type Shape interface {
Area() float64 //some method to ensure any is an Shape type.
}
func Invoke(s Shape, name string, inputs...interface{}) []interface{} {
}
だからこれは大丈夫です
color := Invoke(Circle{}, "GetColor")[0].(Color)
しかし
Invoke(NotAShape{}, "ForBar")
NotAnShape
はシェイプではないため、コンパイルできません。
コンパイル時に最初のタイプについて確信が持てない場合は、次のように、考えられるすべてのタイプを格納するマップを作成できます。
map[string]reflect.Value{
"YourT1" : reflect.ValueOf(YourT1{})
"YourT2" : reflect.ValueOf(YourT2{})
"Circle" : reflect.ValueOf(Cirlce{}) // or reflect.ValueOf(&Circle{})
}