Go の for ループは、ループ変数をループ本体内で変更できない C# の foreach ループとは異なります。 Go では、ループ変数を変更できるため、キャプチャされたクロージャーの動作を別の方法で処理する必要があります。
説明するために、3 つのコードを調べてみましょう。スニペット:
ラボ 1:
l := [](func() (int32, int32)){} for k, v := range m { // Closure captures the last values assigned to k and v from the range l = append(l, func() (int32, int32) { return k, v }) }
ラボ 2:
l := [](func() (int32, int32)){} for k, v := range m { // Closure captures the outer variables k and v (which are modified in the loop) l = append(l, func() (int32, int32) { return k, v }) }
ラボ 3:
l := [](func() (int32, int32)){} for k, v := range m { kLocal, vLocal := k, v // Captures just the values assigned to k and v at the iteration l = append(l, func() (int32, int32) { return kLocal, vLocal }) }
Lab1 と Lab2 では、クロージャはループ本体内のループ変数に割り当てられた最後の値をキャプチャします。ループ変数がループ内で変更されると、不正確な結果が生じる可能性があります。
Lab3 では、正しいアプローチを示します。これは、ローカル変数を使用して、各反復内でループ変数に割り当てられた値を具体的にキャプチャします。この動作は Go のクロージャと一致しており、キャプチャされた変数はデフォルトで参照透過的です。
Go では、for ループ変数のクロージャは参照ではなく値をキャプチャします。ループ中に変更される可能性のある値をキャプチャするには、クロージャに必要な値を割り当てるローカル変数を各反復内で作成する必要があります。このアプローチにより、クロージャ動作が期待どおりであることが保証されます。
以上がGo クロージャはどのようにして for ループ変数を処理し、予期しない動作を防ぐのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。