如何从Go中的字符串方法名调用另一个包的方法

如何从Go中的字符串方法名调用另一个包的方法,go,Go,假设我有两个像这样的包裹 -a -b a有一些类似的方法 func TestOne() { //something } func TestTwo() { //something } 我需要从包b调用包a的方法,但只能通过字符串方法名。就像我得到字符串“TestOne”并调用方法TestOne()。我怎样才能做到这一点 编辑: 我已经读过关于反映。但是reflect需要一个结构,并且函数必须是该结构的成员。如果我的函数不是结构的成员怎么办?只是包中的普通方法。调用方法和被调用方法在不同的包中

假设我有两个像这样的包裹

-a

-b

a有一些类似的方法

 func TestOne() { //something }
 func TestTwo() { //something }
我需要从包b调用包a的方法,但只能通过字符串方法名。就像我得到字符串“TestOne”并调用方法TestOne()。我怎样才能做到这一点

编辑: 我已经读过关于
反映
。但是
reflect
需要一个结构,并且函数必须是该结构的成员。如果我的函数不是结构的成员怎么办?只是包中的普通方法。调用方法和被调用方法在不同的包中。那么


注意。有些方法可能也有参数。

您可以尝试在go中使用reflect。此链接可能对您有所帮助 及


正如他在回答中所说,你可以使用反射

您可以使用reflect.ValueOf方法获取类型的值。然后可以使用MethodByName方法获取函数值。一旦得到函数值,就可以调用call方法来执行它

代码示例

package main

import (
    "fmt"
    "reflect"
)

type TypeOne struct {
}

func (t *TypeOne) FuncOne() {
    fmt.Println("FuncOne")
}

func (t *TypeOne) FuncTwo(name string) {
    fmt.Println("Hello", name)
}

func CallFuncByName(myClass interface{}, funcName string, params ...interface{}) (out []reflect.Value, err error) {
    myClassValue := reflect.ValueOf(myClass)
    m := myClassValue.MethodByName(funcName)
    if !m.IsValid() {
        return make([]reflect.Value, 0), fmt.Errorf("Method not found \"%s\"", funcName)
    }
    in := make([]reflect.Value, len(params))
    for i, param := range params {
        in[i] = reflect.ValueOf(param)
    }
    out = m.Call(in)
    return
}

func main() {
    t1 := &TypeOne{}
    out, err := CallFuncByName(t1, "FuncOne")
    if err != nil {
        panic(err)
    }
    //Return value
    _ = out
    out, err = CallFuncByName(t1, "FuncTwo", "monkey")
    if err != nil {
        panic(err)
    }
    //Return value
    _ = out
}

@icza的相关/可能的副本我阅读了问题和答案。但他们所说的解决方案反映了这一点。和reflect需要一个结构,函数是该结构的成员。如果我的函数不是结构的成员怎么办?只是包中的普通方法。调用方法和被调用方法在不同的包中。然后?那么答案是否定的,如果没有@LightWeight的答案中所示的预填充名称函数映射,您就无法做到这一点。@eror Read
mnagel
对链接问题的回答。这应该是目前来自顶部的第二个答案。只要有函数的句柄,就可以使用reflect调用函数,该句柄可以通过映射获得。您误解了这样一个事实,即不能仅通过反射获得自由函数的句柄。只要您构建一个
map[string]接口{}
,该接口通过自己的名字返回函数,您就可以通过
reflect.ValueOf
后跟
Value.call
Value.CallSlice
@Jsor-Thanx调用函数,兄弟。我用您指定的地图解决了此问题。:)但在我的白痴头脑中仍然存在一个问题——如果我没有地图,我该怎么做呢。如果我的函数不是结构的成员怎么办?只是包中的普通方法。调用方法和被调用方法在不同的包中。然后呢?是的,我是个白痴:)当我看着它的时候我就知道了。无法直接获取包函数。您可以创建要调用的所有函数的映射
funcMap:=map[string]接口{}{“TestOne”:TestOne,“TestTwo”:TestTwo}
然后使用
reflect.ValueOf(funcMap[“TestOne”]).Call()
像上面的示例代码那样执行它。为什么你会是个白痴,兄弟。我是这里问愚蠢问题的人P:谢谢。试一下你刚才描述的。@monkey\p终于找到了一个解决方案,它能满足你的要求
funcMap:=map[string]interface{}
注释中描述的方法是调用不属于结构IMO的方法的正确方法。reflect需要一个结构,函数必须是该结构的成员。如果我的函数不是结构的成员怎么办?只是包中的普通方法。调用方法和被调用方法在不同的包中。那么?
package main

import (
    "fmt"
    "reflect"
)

type TypeOne struct {
}

func (t *TypeOne) FuncOne() {
    fmt.Println("FuncOne")
}

func (t *TypeOne) FuncTwo(name string) {
    fmt.Println("Hello", name)
}

func CallFuncByName(myClass interface{}, funcName string, params ...interface{}) (out []reflect.Value, err error) {
    myClassValue := reflect.ValueOf(myClass)
    m := myClassValue.MethodByName(funcName)
    if !m.IsValid() {
        return make([]reflect.Value, 0), fmt.Errorf("Method not found \"%s\"", funcName)
    }
    in := make([]reflect.Value, len(params))
    for i, param := range params {
        in[i] = reflect.ValueOf(param)
    }
    out = m.Call(in)
    return
}

func main() {
    t1 := &TypeOne{}
    out, err := CallFuncByName(t1, "FuncOne")
    if err != nil {
        panic(err)
    }
    //Return value
    _ = out
    out, err = CallFuncByName(t1, "FuncTwo", "monkey")
    if err != nil {
        panic(err)
    }
    //Return value
    _ = out
}