Golang:从字符串(函数名称)指向函数的指针

Ser*_*mov 21 go

有没有机会从函数的名称获取指向函数的指针,以字符串形式呈现?这需要例如将一些函数作为参数发送到另一个函数.你知道,某种元编程.

谢谢!

zzz*_*zzz 41

Go函数是一等值.您无需恢复动态语言的技巧.

package main

import "fmt"

func someFunction1(a, b int) int {
        return a + b
}

func someFunction2(a, b int) int {
        return a - b
}

func someOtherFunction(a, b int, f func(int, int) int) int {
        return f(a, b)
}

func main() {
        fmt.Println(someOtherFunction(111, 12, someFunction1))
        fmt.Println(someOtherFunction(111, 12, someFunction2))
}
Run Code Online (Sandbox Code Playgroud)

操场


输出:

123
99
Run Code Online (Sandbox Code Playgroud)

如果函数的选择取决于某些仅运行时的已知值,则可以使用映射:

m := map[string]func(int, int) int {
        "someFunction1": someFunction1,
        "someFunction2": someFunction2,
}

...

z := someOtherFunction(x, y, m[key])
Run Code Online (Sandbox Code Playgroud)

  • @zzzz我认为你不会理解这个问题.例如,假设您有一个等待客户端请求的http服务器,那么您可以决定调用哪个后端服务,具体取决于您从URL获取的值.网址是字符串.我不想维护不断增长的地图,而只是想使用函数名作为字符串来调用函数. (4认同)
  • "来自动态语言的糟糕技巧"...你们每个人都试图在Go中使用函数作为地图键的一部分吗?可能不是.Go是一种很棒的语言,但有些东西只是称为"头等舱",甚至是"可比较的".实际上,我希望他们是真正的一流价值观. (3认同)
  • 我认为他意味着他需要在给定函数名称的字符串表示的情况下获取(并且可能最终调用)指向指定函数的指针.我假设您需要以某种方式使用反射包. (2认同)
  • @joshlf13 将字符串函数名映射到函数指针显示在答案中,所以我现在更加困惑了 ;-) (2认同)

mna*_*gel 14

接受的答案答案可能是你应该做的.

这是一种使用反射的方法,它允许传递灵活数量的参数.目前,它需要手动构建支持函数的列表(映射)(请参阅main方法),但这可以改进.

package main

import "fmt"
import "reflect"
import "errors"

func foo() {
    fmt.Println("we are running foo")
}

func bar(a, b, c int) {
    fmt.Println("we are running bar", a, b, c)
}

func Call(m map[string]interface{}, name string, params ... interface{}) (result []reflect.Value, err error) {
    f := reflect.ValueOf(m[name])
    if len(params) != f.Type().NumIn() {
        err = errors.New("The number of params is not adapted.")
        return
    }
    in := make([]reflect.Value, len(params))
    for k, param := range params {
        in[k] = reflect.ValueOf(param)
    }
    result = f.Call(in)
    return
}

func main() {
    // nota bene: for perfect score: use reflection to build this map
    funcs := map[string]interface{} {
            "foo": foo,
            "bar": bar,
    }

    Call(funcs, "foo")
    Call(funcs, "bar", 1, 2, 3)
}
Run Code Online (Sandbox Code Playgroud)

启示/源