🦸

Go言語でクロージャーを使う

2023/07/13に公開

Go by Example: Closures

公式の解説を翻訳しております
Goはクロージャを形成できる匿名関数をサポートしています。無名関数は、名前を付けずにインラインで関数を定義したい場合に便利です。

このintSeq関数は、intSeq本体の中で匿名で定義した別の関数を返す。返された関数は変数iを閉じてクロージャーを形成する。

intSeqを呼び出し、その結果(関数)をnextIntに代入する。この関数値は、nextIntを呼び出すたびに更新されるi値をキャプチャする。

nextIntを数回呼び出して、クロージャーの効果を確認する。

その状態が特定の関数に固有のものであることを確認するには、新しい関数を作ってテストする。

関数の最後の機能は再帰だ

package main

import "fmt"

// func intSeq() func() intは、intSeq()から新しい関数を返します。
// これが、再帰的に呼び出されることにより、クロージャを形成します。
// ここでのクロージャは、それ自体の値を保持している関数です。
// クロージャーとは、それ自体の環境を持つ関数値です。
func intSeq() func() int {
    // iはintSeqに属するローカル変数のように振る舞います。
    i := 0
    // intSeqは、intSeqの中で定義された無名関数を返します。
    return func() int {
        // intSeqの中で定義された無名関数は、iという変数にアクセスします。
        i++
        return i
    }
}

func main() {
    // intSeqを呼び出し、その戻り値(関数)をnextIntに代入します。
    nextInt := intSeq()

    fmt.Println(nextInt())
    fmt.Println(nextInt())
    fmt.Println(nextInt())
    // intSeqから別の関数を新たに作成し、そこからnextIntに代入します。
    newInts := intSeq()
    fmt.Println(newInts())
}

実行結果

hashimotojunichi@hashimotojunichinoMacBook-Pro go-example % go run hello.go
1
2
3
1

まとめ

今回使った匿名関数とは、プログラミング言語の世界では、名前のない関数のことです。
goのクロージャは、このように関数の中で定義された無名関数です。
再帰関数という表現も聞きますが、よく使われるのは再帰という表現です。

Jboy王国メディア

Discussion