Golang反射调用函数

首先,来看看这段 PHP 代码:

1 functionfoobar() {
2     echo"Hello Golang\n";
3 }
4 $funcs= array(
5     "foobar"=> "foobar",
6     "hello" => "foobar",
7 );
8 $funcs["foobar"]();
9 $funcs["hello"]();

它会输出:

1 mikespook@mikespook-laptop:~/Desktop$ phpfoobar.php
2 HelloGolang
3 HelloGolang

用这个方法调用匹配名字的函数,非常有效。


那么,在 Golang 中是否可能用函数的名字来调用某个函数呢?


作为一个静态、编译型语言,答案是否定的……又是肯定的!


在 Golang 中,你不能这样做:

01 func foobar(){
02     //bla...bla...bla...
03 }
04 funcname :="foobar"
05 funcname()
06 不过可以:
07   
08 func foobar(){
09     //bla...bla...bla...
10 }
11 funcs :=map[string]func() {"foobar":foobar}
12 funcs["foobar"]()

但这里有一个限制:这个 map 仅仅可以用原型是“func()”的没有输入参数或返回值的函数。

如果想要用这个方法实现调用不同函数原型的函数,需要用到 interface{}。

这样,就可以添加有着不同函数原型的函数到一个 map 中:

1 func foo(){
2     //bla...bla...bla...
3 }
4 func bar(a, b, cint){
5     //bla...bla...bla...
6 }
7 funcs :=map[string]interface{}{"foo":foo,"bar":bar}

那么如何调用 map 中的函数呢?像这样吗:


funcs["foo"]()

绝对不行!这无法工作!你不能直接调用存储在空接口中的函数。


反射走进我们的生活!在 Golang 中有着叫做“reflect”的包。

01 func Call(mmap[string]interface{}, name string, params ... interface{})(result []reflect.Value, err error) {
02     f= reflect.ValueOf(m[name])
03     iflen(params) != f.Type().NumIn(){
04         err= errors.New("The number of paramsis not adapted.")
05         return
06     }
07     in:= make([]reflect.Value, len(params))
08     fork, param := range params {
09         in[k]= reflect.ValueOf(param)
10     }
11     result= f[name].Call(in)
12     return
13 }
14 Call(funcs,"foo")
15 Call(funcs,"bar", 1,2, 3)

将函数的值从空接口中反射出来,然后使用 reflect.Call 来传递参数并调用它。

没有什么是很难理解的。


[1]http://www.du52.com/text.php?id=92

猜你喜欢

转载自blog.csdn.net/vipally/article/details/40952809