Go では、ループ内のスライスに要素を追加すると、同じ基礎となる配列から作成された既存のスライスの値が予期せず変更される可能性があります。
この問題は、スライスが基礎となる配列値を参照する方法に起因します。スライスに追加すると、既存の配列が変更されるか、新しい配列が作成される場合があります。ただし、スライスが make 関数を使用して作成された場合は、常に同じ基になる配列を参照します。
次のコードを考えてみましょう。
<code class="go">func create(iterations int) []int { a := make([]int, 0) for i := 0; i < iterations; i++ { a = append(a, i) } return a } func main() { sliceFromLoop() sliceFromLiteral() } func sliceFromLoop() { i := create(11) j := append(i, 100) g := append(i, 101) h := append(i, 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) } func sliceFromLiteral() { i := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10} j := append(i, 100) g := append(i, 101) h := append(i, 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) }</code>
sliceFromLoop 内関数では、すべての新しいスライス (j、g、h) は、最初のスライス i と同じ基礎となる配列を共有します。これは、i に追加すると、他のすべてのスライスの最後の要素が変更されることを意味します。
この動作を回避するには、追加する前にスライスのコピーを作成することをお勧めします。それに。コピー関数は、元のスライスと同じ要素を持つ新しいスライスを割り当てます。
<code class="go">func sliceFromLoopFixed() { i := create(11) j := append([]int{}, i..., 100) g := append([]int{}, i..., 101) h := append([]int{}, i..., 102) fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) }</code>
この場合、新しいスライス j、g、h には独自の基礎となる配列があるため、i の値は影響を受けません。
以上が同じ基礎となる配列から作成されたスライスが Go で追加されると予期しない動作を示すのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。