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() に関する問題は、アクション マップに格納されている関数リテラルがループ変数 cmd を参照しているために発生します。このループ変数のインスタンスは 1 つだけであるため、マップに格納されているすべての関数はそれを参照します。
ループが完了すると、cmd の値は cmds スライスの最後の要素「update.」になります。 」その結果、アクション マップ内の関数が実行されると、すべて「update」が出力されます。
この問題を回避するために、loop2() は新しい変数 command を使用してループ変数 cmd をキャプチャします。これにより、反復ごとにループ変数の「切り離された」コピーが作成され、ループの完了後はループ変数の影響を受けません。
その結果、loop2() のアクション マップに格納された各関数は、ループ変数の独自のコピーにより、各関数が正しいコマンドを出力できるようになります。
スライスにまたがる場合は、次の点に注意することが重要です。ループ変数はすべての反復間で共有されます。予期しない動作を回避するには、特にループの後に実行される関数リテラルを使用する場合は、新しい変数を使用してループ変数をキャプチャまたは切り離すことをお勧めします。
以上がGo の「range」ループはループ構造が異なると異なる結果を生み出すのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。