ホームページ >バックエンド開発 >Golang >Go スライスに追加すると元のスライスが変更される場合があるのはなぜですか?

Go スライスに追加すると元のスライスが変更される場合があるのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-10-31 17:00:30856ブラウズ

Why does appending to a Go slice sometimes modify the original slice?

Golang Append のスライス割り当て動作

Go では、スライスに追加する場合、効率的な処理を確保するために割り当て動作を理解する必要があります。

組み込み API ドキュメントによると、append() 関数は、既存のスライスの容量が不十分な場合、データを再割り当てして新しい配列ブロックにコピーします。これにより、スライス記述子の性質と、append() から返されるスライスについて疑問が生じます。

組み合わせを生成するために提供された再帰アルゴリズムでは、append() 関数を使用してスライスを段階的に構築します。ただし、AddOption 関数からチャネル経由で送信されたスライスは、送信後に変更されることが観察されています。これは、append() が新しいスライスを返すという期待と矛盾します。

この明らかな不一致を解決するには、スライスのデータ型とその基礎となる表現の区別を明確にすることが不可欠です。スライス記述子は、2 つの整数 (長さと容量) と実際のデータへのポインタで構成されます。 append() が新しいスライスを作成すると、新しいスライス記述子が生成されますが、元のスライスと同じデータ ポインタは維持されます。したがって、いずれかのスライス記述子に加えられた変更は両方のスライスに影響します。

これを説明するために、次のコード スニペットを考えてみましょう。

<code class="go">s := make([]int, 0, 5)
s = append(s, []int{1, 2, 3, 4}...)

a := append(s, 5)
fmt.Println(a)  // [1 2 3 4 5]

b := append(s, 6)
fmt.Println(b)  // [1 2 3 4 6]
fmt.Println(a)  // [1 2 3 4 6]</code>

最初、 s の容量は 5 で、make を使用して構築されます。 ()。 append() は、別のスライスの要素を s に追加するために使用されます。次に、異なる要素を持つ s に対して append() を使用して、2 つの新しいスライス a と b が作成されます。出力を観察すると、a と b の両方に同じデータが含まれており、同じデータ ポインターを共有していることがわかります。これは、上で説明した動作を示しています。

効率的なスライス操作を保証するには、append() のこの割り当て動作を理解することが重要です。既存のスライスの容量が十分な場合、append() は既存のデータ ポインターを直接操作するため、より効率的になります。

以上がGo スライスに追加すると元のスライスが変更される場合があるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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