次のコラム golang チュートリアル では、golang におけるクロージャの意味と使い方を紹介します。困っている友人の役に立てば幸いです。
#クロージャとは何ですか?
Go 関数はクロージャになることができます。クロージャは、関数本体の外側の変数を参照する関数値です。この関数は、参照された変数にアクセスして値を割り当てることができます。つまり、関数は変数に「バインド」されています。 私の不確かな理解ですが、クロージャはクラスのインスタンスに相当し、関数本体の外にある変数はこのインスタンスに格納されている変数に相当します。
クロージャがない場合、関数は 1 回限りのトランザクションです。関数の実行後、関数内の変数の値は変更できません (メモリを解放する必要があります)。クロージャが終了すると、関数は変数の値になります。変数が解放されない限り、関数は常に有効で排他的です。そのため、関数内の変数の値は後で変更できます(この方法ではメモリがgo によって再利用されることはなく、常に There にキャッシュされます)。 クロージャの主な重要性変数のスコープを縮小し、グローバル変数の汚染を軽減します。次のような蓄積をグローバル変数を使用して実装すると、グローバル変数は他の変数によって簡単に汚染されてしまいます。同時に、n 個のアキュムレータを実装したい場合は、毎回 n 個のグローバル変数が必要になります。バックパックを使用すると、生成された各アキュムレータmyAdder1, myAdder2 := adder(), adder() は独自の独立した合計を持ち、合計は myAdder1.sum および myAdder2.sum と見なすことができます。
関数を実装できます!
package mainimport ( "fmt")func adder() func(int) int { sum := 0 return func(x int) int { sum += x return sum }}func main() { myAdder := adder() // 从1加到10 for i := 1; i <= 10; i++ { myAdder(i) } fmt.Println(myAdder(0)) // 再加上45 fmt.Println(myAdder(45))}
55 // 1+...+10 100
例
クロージャを使用してフィボナッチ数列を実装するpackage mainimport ( "fmt")func fibonacci() func() int { b0 := 0 b1 := 1 return func() int { tmp := b0 + b1 b0 = b1 b1 = tmp return b1 }}func main() { myFibonacci := fibonacci() for i := 1; i <= 5; i++ { fmt.Println(myFibonacci()) }}
1 2 3 5 8
誤りやすい点
func B() []func() { b := make([]func(), 3, 3) for i := 0; i < 3; i++ { b[i] = func() { fmt.Println(i) } } return b}func main() { c := B() c[0]() c[1]() c[2]()}
// 因为都引用i,i最后变成了3 3 3 3
package mainimport ( "fmt")func B() []func() { b := make([]func(), 3, 3) for i := 0; i < 3; i++ { j := i b[i] = func() { fmt.Println(j) } } return b}func main() { c := B() c[0]() c[1]() c[2]()}
package mainimport ( "fmt")func B() []func() { b := make([]func(), 3, 3) for i := 0; i < 3; i++ { b[i] = func(j int) func(){ return func() { fmt.Println(j) } }(i) } return b}func main() { c := B() c[0]() c[1]() c[2]()}
以上がgolangにおけるクロージャの意味と使い方をご存知ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。