ホームページ >バックエンド開発 >Golang >Go の「range」ループはループ構造が異なると異なる結果を生み出すのはなぜですか?

Go の「range」ループはループ構造が異なると異なる結果を生み出すのはなぜですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-19 18:20:10988ブラウズ

Why Does Go's `range` Loop Produce Different Results with Varying Loop Structures?

Go のさまざまなループのバリエーションを理解する

Go でスライスを反復処理するとき、range メソッドを使用すると、予期しない動作が発生する可能性があります。異なるループのバリエーションが異なる結果を生み出す理由を詳しく見てみましょう。

問題

ループのバリエーションとして次の 2 つを考えてみましょう:

loop1() {
    for _, cmd := range cmds {
        // Store a function literal that references the loop variable cmd
        actions[cmd] = func() {
            fmt.Println(cmd)
        }
    }
}
loop2() {
    for i, cmd := range cmds {
        // Capture the loop variable cmd using a new variable
        command := cmds[i]
        actions[cmd] = func() {
            fmt.Println(command)
        }
    }
}

これらのループの実行結果別の出力:

  • loop1(): 「update」を 3 回出力します
  • loop2(): 「delete」、「update」を出力します"、および "作成"

説明

loop1() に関する問題は、アクション マップに格納されている関数リテラルがループ変数 cmd を参照しているために発生します。このループ変数のインスタンスは 1 つだけであるため、マップに格納されているすべての関数はそれを参照します。

ループが完了すると、cmd の値は cmds スライスの最後の要素「update.」になります。 」その結果、アクション マップ内の関数が実行されると、すべて「update」が出力されます。

この問題を回避するために、loop2() は新しい変数 command を使用してループ変数 cmd をキャプチャします。これにより、反復ごとにループ変数の「切り離された」コピーが作成され、ループの完了後はループ変数の影響を受けません。

その結果、loop2() のアクション マップに格納された各関数は、ループ変数の独自のコピーにより、各関数が正しいコマンドを出力できるようになります。

結論

スライスにまたがる場合は、次の点に注意することが重要です。ループ変数はすべての反復間で共有されます。予期しない動作を回避するには、特にループの後に実行される関数リテラルを使用する場合は、新しい変数を使用してループ変数をキャプチャまたは切り離すことをお勧めします。

以上がGo の「range」ループはループ構造が異なると異なる結果を生み出すのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。