Go は関数呼び出しをパラメーターとして使用する型として直接表現できますか?

Mary-Kate Olsen
リリース: 2024-10-29 03:29:02
オリジナル
859 人が閲覧しました

Can Go directly represent function calls as a type for use as parameters?

関数呼び出しの Go タイプ

go や defer などのキーワードを使用する場合、パラメーターとして関数呼び出しが必要です。しかし、特に引数として関数呼び出し (単に関数自体ではなく) を期待する関数を作成する場合に、同様の方法で使用できる特定の型はありますか?

制限事項と回避策

Go は、この機能を直接可能にする型を提供しません。代わりに、関数型の変数または値を使用し、それらを関数であるかのように後で呼び出すことができます。例:

<code class="go">func myFunc() {
    fmt.Println("hi")
}

func main() {
    var f func()
    f = myFunc
    f() // This calls the function value stored in f: myFunc in this example
}</code>
ログイン後にコピー

コメントで言及されている目的の機能を実現するには、関数呼び出しと引数を func() 内にラップし、それを利用します。例:

<code class="go">func launch(f func()) {
    fmt.Println("Before launch")
    go func() {
        defer fmt.Println("After completion")
        f()
    }()
}</code>
ログイン後にコピー

使用法:

<code class="go">func main() {
    launch(func() {
        fmt.Println("Hello, playground")
    })

    time.Sleep(time.Second)
}</code>
ログイン後にコピー

出力:

Before launch
Hello, playground
After completion
ログイン後にコピー

このメソッドには直接的な回避策は含まれません。パラメータが変更された場合は、launch() を呼び出す前にコピーを作成し、そのコピーを関数リテラル (クロージャ) 内で使用します。

自動パラメータ保存の模倣

特定の関数の場合と入力し、同一のシグネチャを持つヘルパー関数を作成し、パラメーターのない関数を返します。返された関数はクロージャとして機能し、パラメータを指定して元の関数を呼び出します。ヘルパー関数を呼び出すと、パラメーターが効果的に保存され、defer の動作が模倣されます:

<code class="go">func wrapPrintln(s string) func() {
    return func() {
        fmt.Println(s)
    }
}</code>
ログイン後にコピー

Usage:

<code class="go">launch(wrapPrintln(s))</code>
ログイン後にコピー

Using Reflection

Reflection手動コピーの必要性を排除できますが、このアプローチでは関数を呼び出すのではなくパラメーターとして渡す必要があります。また、リフレクションのオーバーヘッドにより遅くなります。

<code class="go">func launch(f interface{}, params ...interface{}) {
    fmt.Println("Before launch")
    go func() {
        defer fmt.Println("After completion")
        pv := make([]reflect.Value, len(params))
        for i, v := range params {
            pv[i] = reflect.ValueOf(v)
        }
        reflect.ValueOf(f).Call(pv)
    }()
}</code>
ログイン後にコピー

使用例:

<code class="go">func main() {
    i, s := 1, "Hello, playground"

    launch(fmt.Printf, "%d %q\n", i, s)
    i, s = 2, "changed"

    time.Sleep(time.Second)
}</code>
ログイン後にコピー

出力:

Before launch
1 "Hello, playground"
After completion
ログイン後にコピー

例外: メソッド値

パラメータの自動保存を利用できる例外の 1 つは、メソッド値の場合です。 x が静的型 T を持ち、T のメソッド セットにメソッド M が含まれている場合、x.M (呼び出しなし) は、式の結果 (関数値) が呼び出されたときにレシーバーとして x のコピーをキャプチャするメソッド値を表します。

以上がGo は関数呼び出しをパラメーターとして使用する型として直接表現できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート