感谢@Jeremy Wall,我相信我能够解决我的问题。基本问题是在上调用动态命名方法
interface{}。有4种情况。interface{}基础数据是价值,接收者是价值interface{}基础数据是指针,接收者是值interface{}基础数据是值,接收者是指针interface{}基础数据是指针,接收者是指针
使用反射,我们可以确定接口的基础值。然后,使用进一步的反射,我们可以生成当前数据类型的替代数据类型。如果传入的数据是一个值,我们需要生成一个指向它的指针
value := reflect.ValueOf(data)if value.Type().Kind() == reflect.Ptr { ptr = value value = ptr.Elem() // acquire value referenced by pointer} else { ptr = reflect.New(reflect.TypeOf(i)) // create new pointer temp := ptr.Elem() // create variable to value of pointer temp.Set(value) // set value of variable to our passed in value}现在我们有了两种数据类型,我们可以简单地使用每种数据类型来检查现有方法
var finalMethod reflect.Valuemethod := value.MethodByName(methodName)if method.IsValid() { finalMethod = method}// check for method on pointermethod = ptr.MethodByName(methodName)if method.IsValid() { finalMethod = method}if (finalMethod.IsValid()) { return finalMethod.Call([]reflect.Value{})[0].String()}因此,考虑到这一点,我们可以有效地动态调用任何方法,无论是声明为
*receiver还是
receiver。
完整的概念证明:http://play.golang.org/p/AU-
Km5VjZs
package mainimport ( "fmt" "reflect")type Test struct { Start string}// value receiverfunc (t Test) Finish() string { return t.Start + "finish"}// pointer receiverfunc (t *Test) Another() string { return t.Start + "another"}func CallMethod(i interface{}, methodName string) interface{} { var ptr reflect.Value var value reflect.Value var finalMethod reflect.Value value = reflect.ValueOf(i) // if we start with a pointer, we need to get value pointed to // if we start with a value, we need to get a pointer to that value if value.Type().Kind() == reflect.Ptr { ptr = value value = ptr.Elem() } else { ptr = reflect.New(reflect.TypeOf(i)) temp := ptr.Elem() temp.Set(value) } // check for method on value method := value.MethodByName(methodName) if method.IsValid() { finalMethod = method } // check for method on pointer method = ptr.MethodByName(methodName) if method.IsValid() { finalMethod = method } if (finalMethod.IsValid()) { return finalMethod.Call([]reflect.Value{})[0].Interface() } // return or panic, method not found of either type return ""}func main() { i := Test{Start: "start"} j := Test{Start: "start2"} fmt.Println(CallMethod(i, "Finish")) fmt.Println(CallMethod(&i, "Finish")) fmt.Println(CallMethod(i, "Another")) fmt.Println(CallMethod(&i, "Another")) fmt.Println(CallMethod(j, "Finish")) fmt.Println(CallMethod(&j, "Finish")) fmt.Println(CallMethod(j, "Another")) fmt.Println(CallMethod(&j, "Another"))}


