匿名関数を使用した Go 同時実行ループで同じ値が出力されるのはなぜですか?

Susan Sarandon
リリース: 2024-11-24 08:41:25
オリジナル
320 人が閲覧しました

Why Do Go Concurrency Loops with Anonymous Functions Print the Same Value?

For ループと匿名関数を使用した Go 同時実行の予期せぬ動作を理解する

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()
}
ログイン後にコピー

驚くべきことに、このコードは、予想される "2, 4, 1, 5," の代わりに "6, 6, 6, 6, 6" を出力します。 3.」この異常は、匿名関数によって作成されたクロージャに起因すると考えられます。

Go では、クロージャは周囲のスコープから変数をキャプチャする関数です。上記のコードでは、各匿名関数が変数 i をキャプチャします。ただし、for ループが反復されると、i はすでに 5 になります。これは、すべてのクロージャが同じ i の値、つまり 6 をキャプチャすることを意味します。

この問題を解決するには、i を引数として渡すことができます。無名関数。そうすることで、各クロージャによってキャプチャされる i のローカル コピーを作成し、各ゴルーチンが正しい値を出力するようにします:

func main() {
    var wg sync.WaitGroup

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go func(i int) {
            fmt.Println(i)
            time.Sleep(time.Second * 1)
            wg.Done()
        }(i)
    }

    wg.Wait()
}
ログイン後にコピー

以上が匿名関数を使用した Go 同時実行ループで同じ値が出力されるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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