在 Golang 中用名字調用函數

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

上個星期,我寫了篇《Function call by name in Golang》。由於是英文的,所以被人詬病(說誰,誰知道!)。好吧,現在用中文重新寫一遍。

Golang 中的函數跟 C 的一樣,是個代碼塊,不過它可以像其他類型那樣賦值給一個變數。

如果你對函數不熟悉,《Codewalk: First-Class Functions in Go》應該是個不錯的起點。已經有所瞭解?那麼繼續吧!

首先,來看看這段 PHP 代碼:

function foobar() {    echo "Hello Golang\n";}$funcs = array(    "foobar" => "foobar",    "hello"  => "foobar",);$funcs["foobar"]();$funcs["hello"]();

它會輸出:

mikespook@mikespook-laptop:~/Desktop$ php foobar.php Hello GolangHello Golang

用這個方法調用匹配名字的函數,非常有效。

那麼,在 Golang 中是否可能用函數的名字來調用某個函數呢?

作為一個靜態、編譯型語言,答案是否定的……又是肯定的

在 Golang 中,你不能這樣做:

func foobar() {    // bla...bla...bla...}funcname := "foobar"funcname()

不過可以:

func foobar() {    // bla...bla...bla...}funcs := map[string]func() {"foobar":foobar}funcs["foobar"]()

但這裡有一個限制:這個 map 僅僅可以用原型是“func()”的沒有輸入參數或傳回值的函數。
如果想要用這個方法實現調用不同函數原型的函數,需要用到 interface{}。

是啊!interface{},跟 C 中的 void 指標類似。還記得這個東西嗎?不記得了?沒事,看看這個吧:《The Go Programming Language Specification:Interface types》。

這樣,就可以添加有著不同函數原型的函數到一個 map 中:

func foo() {    // bla...bla...bla...}func bar(a, b, c int) {    // bla...bla...bla...}funcs := map[string]interface{}{"foo":foo, "bar":bar}

那麼如何調用 map 中的函數呢?像這樣嗎:

funcs["foo"]()

絕對不行!這無法工作!你不能直接調用儲存在空介面中的函數。

反射走進我們的生活!在 Golang 中有著叫做“reflect”的包。你是否瞭解反射了呢?
如果還沒有,那麼閱讀一下這個:《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)

將函數的值從空介面中反射出來,然後使用 reflect.Call 來傳遞參數並調用它。
沒有什麼是很難理解的。

我已經完成了一個包來實現這個功能,在這裡:https://bitbucket.org/mikespook/golib/src/27c65cdf8a77/funcmap.

希望這有些協助。好運,地鼠們!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.