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
- Проверьте, что "любой" является типом структуры
- Проверьте, что "любой" имеет метод "name"
- Проверка количества входных параметров метода "имя" равна длине аргументов
- Реализация
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(NotAnShape{}, "ForBar")
не может быть скомпилировано, потому что NotAnShape
не является Shape.
Если вы не уверены, какой первый тип будет использоваться во время компиляции, вы можете построить карту для хранения всех возможных типов, как этот.
map[string]reflect.Value{
"YourT1" : reflect.ValueOf(YourT1{})
"YourT2" : reflect.ValueOf(YourT2{})
"Circle" : reflect.ValueOf(Cirlce{}) // or reflect.ValueOf(&Circle{})
}