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")
}
Really the code needs to check the method's input number and even whether the method itself exists.
You can reference this http://gowalker.org/reflect#Type
- Check "any" is a struct type
- Check "any" has "name" method
- Check the number of method "name" input parameters is equal the length of args
- Implement
ret
by reflect.Value.Interface()
and be careful the Ptr type;
Or you can use SomeInterface{}
instead of directly using interface{}
to ensure this "any" type, like this:
type Shape interface {
Area() float64 //some method to ensure any is an Shape type.
}
func Invoke(s Shape, name string, inputs...interface{}) []interface{} {
}
so this is OK
color := Invoke(Circle{}, "GetColor")[0].(Color)
but
Invoke(NotAShape{}, "ForBar")
can't be compiled because NotAnShape
isn't a Shape.
If you can't be sure about the first type at compile time, you can build a map to store all possible type, like this:
map[string]reflect.Value{
"YourT1" : reflect.ValueOf(YourT1{})
"YourT2" : reflect.ValueOf(YourT2{})
"Circle" : reflect.ValueOf(Cirlce{}) // or reflect.ValueOf(&Circle{})
}