The golang’s function is a code block like C’s, but it can also be assigned to a variable as its other types.
If you are not familiar with the function, Codewalk: First-Class Functions in Go should be a good starting point for you. Already known it? Let’s go on.
First of all, look at this PHP codes:
function foobar() {
echo "Hello Golang\n";
}
$funcs = array(
"foobar" => "foobar",
"hello" => "foobar",
);
$funcs["foobar"]();
$funcs["hello"]();
It will print:
mikespook@mikespook-laptop:~/Desktop$ php foobar.php Hello Golang Hello Golang
It is very useful for calling a function with name matching.
So, is it possible to call a function by its name in Golang?
As a static, compiled programming language, the answer is No … and YES!
You can not do this in Golang:
func foobar() {
// bla...bla...bla...
}
funcname := "foobar"
funcname()
You can do:
func foobar() {
// bla...bla...bla...
}
funcs := map[string]func() {"foobar":foobar}
funcs["foobar"]()
But here’s a limitation that the map only work with the prototype “func()”, no input parameters and return arguments.
If you want to call some functions have different function’s prototypes, the interface{} should be used.
Yep! interface{}, like the void pointer in C. Remember that? No? Never mind! Read this: The Go Programming Language Specification:Interface types.
Then we could add functions with different prototypes into one map:
func foo() {
// bla...bla...bla...
}
func bar(a, b, c int) {
// bla...bla...bla...
}
funcs := map[string]interface{}{"foo":foo, "bar":bar}
How to call a function in the map? like this?
funcs["foo"]()
NO! It does not work! You can not call a function stored in a empty interface variable directly.
Dadadada…
Reflection comes to us! It is a package called “reflect” in Golang. Do you know reflection already?
If not, just read this: Laws of reflection.
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
}
Call(funcs, "foo")
Call(funcs, "bar", 1, 2, 3)
Reflecting the function variable, use reflect.Call to call it and pass parameters into it at the same time.
Nothing could be hard to understand.
I’ve done a package for this functional: https://bitbucket.org/mikespook/golib/src/27c65cdf8a77/funcmap.
Hope this helps. Have a good time, gophers!
所有涉及到go的函数均应该为func关键字而非function:比如:
function foo() {
// bla…bla…bla…
}
function bar(a, b, c int) {
// bla…bla…bla…
}
Fixed, thx!
[...] 在 Golang 中用名字调用函数 Golang Add comments 七 122012 #leftcontainerBox { float:left; position: fixed; top: 60%; left: 70px; } #leftcontainerBox .buttons { float:left; clear:both; margin:4px 4px 4px 4px; padding-bottom:2px; } #bottomcontainerBox { width: 50%; padding-top: 1px; } #bottomcontainerBox .buttons { float: left; margin: 4px 4px 4px 4px; } 上个星期,我写了篇《Function call by name in Golang》。由于是英文的,所以被人诟病(说谁,谁知道!)。好吧,现在用中文重新写一遍。 [...]
How about:
package mypackage
func foo (s string, i int) (bool, error) {
return false, nil
}
func bar (opts []string) (int, error) {
return 456, nil
}
var Foo func(string, int) (bool, error)
var Bar func([]string) (int, error)
func init() {
Foo = foo
Bar = bar
}
func main() {
b, err := Foo(“abc”, 345)
i, err := Bar([]string{“abc”, “edf”})
}
You could use this for exporting private functions only for testing f.i..
Johan