Is there any chance to get pointer to function from function's name, presented as string? This is needed for example to send some function as argument to another function. Some sort of metaprogramming, you know.
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])
I'm not entirely clear on what you're wanting to do. The accepted answer should cover the fundamentals of anything you're trying to do.
I would like to add that the crypto
package has an interesting way of indirectly registering other packages. Specifically take a look at crypto.go.
Essentially how it works is the crypto
package has an empty map like this:
var regFuncs = make(map[key]func (arg) result)
Where "key" would be a unique type (of int, string, etc..) and the value would be the function prototype you're expecting.
A package would then register itself using the init function:
func init() {
master.RegisterFunc("name", myFunc)
}
The package itself would be included using import _ "path/to/package"
.
And then the master package would have some way of fetching that function.
With crypto
, you can use sha 256 like this:
crypto.SHA256.New()
But you have to first include it in your main like this:
import _ "crypto/sha256"
Hopefully that helps.
The accepted answer answer is probably what you should do.
Here is an approach using reflection that allows to pass a flexible number of arguments as well. Currently it requires building a list (map) of supported functions manually (see main
method), but this could be improved.
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)
}
If the function is a 'Method', you can use reflect.Value.MethodByName