25

関数の名前から関数へのポインタを文字列として取得する機会はありますか? これは、たとえば、ある関数を引数として別の関数に送信するために必要です。ある種のメタプログラミングですね。

4

4 に答える 4

17

受け入れられた答えの答えは、おそらくあなたがすべきことです。

これは、柔軟な数の引数を渡すこともできるリフレクションを使用したアプローチです。現在、サポートされている関数のリスト (マップ) を手動で作成する必要があります (mainメソッドを参照)。ただし、これは改善される可能性があります。

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)
}

インスピレーション/ソース

于 2013-08-03T07:52:29.383 に答える
4

関数が「メソッド」の場合、reflect.Value.MethodByName を使用できます

ここで反映のドキュメントを参照してください

于 2014-09-21T14:58:10.627 に答える
3

あなたが何をしたいのか完全にはわかりません。受け入れられた答えは、あなたがやろうとしていることの基本をカバーする必要があります。

cryptoパッケージには、他のパッケージを間接的に登録する興味深い方法があることを付け加えたいと思います。具体的にはcrypto.goを見てください。

基本的に、cryptoパッケージには次のような空のマップがあります。

var regFuncs = make(map[key]func (arg) result)

ここで、「キー」は一意の型 (int、string など) であり、値は期待する関数プロトタイプです。

次に、パッケージは init 関数を使用して自身を登録します。

func init() {
    master.RegisterFunc("name", myFunc)
}

パッケージ自体は、 を使用してインクルードされimport _ "path/to/package"ます。

そして、マスターパッケージには、その関数を取得する何らかの方法があります。

ではcrypto、次のように sha 256 を使用できます。

crypto.SHA256.New()

ただし、最初に次のようにメインに含める必要があります。

import _ "crypto/sha256"

うまくいけば、それは役に立ちます。

于 2013-08-02T21:20:29.187 に答える