首先,來看看這段 PHP 代碼:
它會輸出:
1 |
mikespook@mikespook-laptop:~/Desktop$ phpfoobar.php |
用這個方法調用匹配名字的函數,非常有效。
那麼,在 Golang 中是否可能用函數的名字來調用某個函數呢?
作爲一個靜態、編譯型語言,答案是否定的……又是肯定的!
在 Golang 中,你不能這樣做:
11 |
funcs :=map[string]func() { "foobar" :foobar} |
但這裏有一個限制:這個 map 僅僅可以用原型是“func()”的沒有輸入參數或返回值的函數。
如果想要用這個方法實現調用不同函數原型的函數,需要用到 interface{}。
這樣,就可以添加有着不同函數原型的函數到一個 map 中:
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 |
if len(params) != f.Type().NumIn(){ |
04 |
err= errors.New( "The number of paramsis not adapted." ) |
07 |
in:= make([]reflect.Value, len(params)) |
08 |
for k, param := range params { |
09 |
in[k]= reflect.ValueOf(param) |
11 |
result= f[name].Call(in) |
15 |
Call(funcs, "bar" , 1,2, 3) |
將函數的值從空接口中反射出來,然後使用 reflect.Call 來傳遞參數並調用它。
沒有什麼是很難理解的。
[1]http://www.du52.com/text.php?id=92