无论接收器类型如何,接口{}上的动态调用方法

无论接收器类型如何,接口{}上的动态调用方法,第1张

无论接收器类型如何,接口{}上的动态调用方法

感谢@Jeremy Wall,我相信我能够解决我的问题。基本问题是在上调用动态命名方法

interface{}
。有4种情况。

  1. interface{}
    基础数据是价值,接收者是价值
  2. interface{}
    基础数据是指针,接收者是值
  3. interface{}
    基础数据是值,接收者是指针
  4. 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"))}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5462973.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-12
下一篇2022-12-12

发表评论

登录后才能评论

评论列表(0条)

    保存