Go で同時実行コードを記述する場合、匿名関数の動作を理解することが重要です。この例では、for ループと匿名関数が予期しない出力を生成するシナリオを検討します。
func main() { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go func() { fmt.Println(i) time.Sleep(time.Second * 1) wg.Done() }() } wg.Wait() }
このコードを実行すると、驚くべきことに「6, 6, 6,予想されるシーケンス「2、4、1、5、3」ではなく、「6、6」です。これは、ゴルーチンが起動された後も for ループが変数 i を更新し続けるためです。
上記のコードの匿名関数はクロージャです。クロージャは、関数の作成時に関数の本体で使用される変数をキャプチャします。この場合、変数 i はゴルーチンの起動時に取得されます。ただし、ループはゴルーチンの開始後も i を更新し続けます。
i が 5 より大きくなるまでループは終了しないため、ゴルーチンが最終的に実行されるとき、i は 6 になります。したがって、各ゴルーチンは、クロージャでキャプチャされた i の値 (この場合は 6) を出力します。期待される出力は、変数 i が引数として匿名関数に渡された場合にのみ観察され、呼び出し時に値のコピーが事実上作成されます。
以上がGo 同時実行の例で、予想されるシーケンスではなく「6, 6, 6, 6, 6」が出力されるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。