Go では、パラメータが渡された匿名関数はクロージャとは異なる動作をすることがあります。この記事では、この区別とその影響について詳しく説明します。
クロージャの例:
func main() { done := make(chan bool, 1) go func() { time.Sleep(50 * time.Millisecond) done <- true }() <-done }
このクロージャでは、匿名関数にはパラメータがなく、代わりに周囲のスコープに存在する Done チャネルにアクセスします。
パラメータの例:
func main() { done := make(chan bool, 1) go func(c chan bool) { time.Sleep(50 * time.Millisecond) c <- true }(done) <-done }
この場合、匿名関数はパラメータ c を受け取ります。
パラメータを使用する場合
匿名関数にパラメータを渡すことは、変数の共有が予期しない動作を引き起こす可能性があるシナリオで主に有益です。次の例を考えてみましょう。
for i := 0; i < 3; i++ { go func() { fmt.Println(i) }() // Closure }
ここで、匿名関数はクロージャです。つまり、for ループで定義された i 変数を参照します。すべてのゴルーチンは同じ i 変数を共有するため、「0」、「1」、「2」が出力されることが予想される場合でも、「3」(ループ完了後の i の最終値) が出力されます。
この問題を修正するには、i をパラメータとして渡すことができます。
for i := 0; i < 3; i++ { go func(v int) { fmt.Println(v) }(i) // Parameter }
これで、各ゴルーチンは関数が呼び出されたときに i 変数のコピーを受け取ります。その結果、正しい出力: "0"、"1"、および "2" が得られます。
結論
クロージャーを使用すると、周囲のスコープ内の変数に簡単にアクセスできます。パラメーターを渡すと、特に同時シナリオで共有変数を扱うときに、より詳細な制御が提供され、予測可能な動作が保証されます。
以上がGo 匿名関数でパラメータとクロージャを使用する場合は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。