ホームページ >バックエンド開発 >Golang >同じ基礎となる配列から作成されたスライスが Go で追加されると予期しない動作を示すのはなぜですか?

同じ基礎となる配列から作成されたスライスが Go で追加されると予期しない動作を示すのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-04 02:15:29918ブラウズ

Why do slices created from the same underlying array exhibit unexpected behavior when appended to in Go?

予期しないスライス追加動作

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 サイトの他の関連記事を参照してください。

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