スライスの追加操作で予期しない動作が発生する
Go では、ループ反復中に要素をスライスに追加してから新しい要素を作成すると、予期しない動作が発生することがあります。結果に基づいてスライスします。この動作は、参照をスライスする基礎となる配列に由来します。
次のコードを考えてみましょう:
<code class="go">func create(iterations int) []int { a := make([]int, 0) for i := 0; i < iterations; i++ { a = append(a, i) } return a }</code>
create(11) を呼び出して結果を i に代入すると、後続の各追加が期待されます。操作 (j := append(i, 100)、g := append(i, 101)、および h := append(i, 102)) を使用して、個別の値を持つ新しいスライスを作成します。ただし、観察された動作は、インデックスに関係なく、これらの新しいスライスの最後の要素が常に 102 であるということです。
これは、すべての追加が同じ基礎となる配列を変更するために発生します。要素をスライスに追加すると長さが変更され、配列の再割り当てが発生する可能性があります。新しい配列が割り当てられると、古い配列への以前の参照はすべて無効になります。ただし、追加がバッキング配列の容量を超える場合は常に新しい配列が割り当てられるため、
スライス リテラルは期待どおりに動作します。
慣用的なアプローチ
既存のスライスに基づいて複数の新しいスライスを作成するときに予測可能な動作を保証するための慣用的なアプローチは、要素を追加する前にスライスをコピーすることです。
<code class="go">func makeFromSlice(sl []int) []int { result := make([]int, len(sl)) copy(result, sl) return result }</code>
コピーを実行すると、新しいバッキング配列が作成され、結果のスライスに加えられた変更が元のスライスに影響を与えないことが保証されます。
以上がGo でループ内のスライスに追加すると予期しない結果が生じるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。