是否有机会从函数名称中获取指向函数的指针,以字符串形式呈现?例如,需要将某个函数作为参数发送给另一个函数。某种元编程,你知道的。
4 回答
Go functions are first class values. You don't need to revert to the tricks from dynamic languages.
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))
}
Output:
123
99
If the selection of the function depends on some run-time-only known value, you can use a map:
m := map[string]func(int, int) int {
"someFunction1": someFunction1,
"someFunction2": someFunction2,
}
...
z := someOtherFunction(x, y, m[key])
接受的答案答案可能是您应该做的。
这是一种使用反射的方法,它也允许传递灵活数量的参数。目前它需要手动构建支持功能的列表(地图)(参见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)
}
如果函数是“方法”,则可以使用 reflect.Value.MethodByName
在此处查看反映文档
我不完全清楚你想要做什么。接受的答案应该涵盖您尝试做的任何事情的基础。
我想补充一点,这个crypto
包有一种有趣的方式来间接注册其他包。具体看看crypto.go。
本质上它的工作原理是crypto
包有一个像这样的空地图:
var regFuncs = make(map[key]func (arg) result)
其中“key”将是唯一类型(int、string 等),而 value 将是您期望的函数原型。
然后,一个包将使用 init 函数注册自己:
func init() {
master.RegisterFunc("name", myFunc)
}
包本身将使用import _ "path/to/package"
.
然后主包将有某种方式来获取该功能。
使用crypto
,您可以像这样使用 sha 256:
crypto.SHA256.New()
但是你必须首先将它包含在你的 main 中,如下所示:
import _ "crypto/sha256"
希望这会有所帮助。