Go の append() オペレーションのスライス動作の背後にある謎は何ですか?

Barbara Streisand
リリース: 2024-10-23 13:45:02
オリジナル
987 人が閲覧しました

What's the Mystery Behind Slice Behavior in append() Operations in Go?

スライスでの append() の動作をわかりやすく説明する

Go では、次のようなコードに遭遇するのが一般的です。

<code class="go">func main() {
    slice := make([]int, 10, 10)
    slice[0] = 0
    slice[1] = 1

    slice1 := slice
    slice1[0] = 10000
    fmt.Println(slice)

    slice1 = append(slice1, 100)
    slice1[0] = 20000

    fmt.Println(slice)
}</code>
ログイン後にコピー

実行時このコードを見ると、何か奇妙なことに気づくでしょう:

[10000 1 0 0 0 0 0 0 0 0]
[10000 1 0 0 0 0 0 0 0 0]
ログイン後にコピー

直感的には、slice とslice1 は同じ基礎となる配列への参照であると思われるかもしれません。ただし、この観察により次のような疑問が生じます。スライス 1 に対する追加操作の後、スライスが変更されないのはなぜですか?

スライスの性質を理解する

この謎を解明するには、次のことが不可欠です。 Go におけるスライスの基本的な性質を理解する。スライスはポインタではありません。これらは配列のカプセル化です。具体的には、スライスは次の 3 つの要素で構成されます。

  • 基になる配列の先頭へのポインタ
  • スライスのサイズ
  • スライスの容量 (再割り当てなしの最大サイズ) )

slice1 をスライスに割り当てるときは、スライスと同じ基になる配列を指す新しいスライス ヘッダーを作成することになります。その結果、slice1 に加えられた変更はすべてスライスに直接反映されます。

append() の影響

次に、append() の影響を分析してみましょう。スライス1。 append() 関数は引数としてスライスを受け取り、新しいスライスを返します。この新しいスライスは、元のスライスと同じ基になる配列を参照する場合もあれば、参照しない場合もあります。

この場合、スライスには最初はその長さに等しい容量があるため、0 個以上の要素を持つ append() 操作が必要になります。新しい、より大きな配列を作成します。これはまさに、slice1 = append(slice1, 100) が行うことです。新しい配列を割り当て、古い配列の内容をコピーして、新しいスライス ヘッダーを返します。

結果のスライス ヘッダーをスライス 1 に割り当てると、スライス 1 内の以前のスライス ヘッダーが置き換えられます。これは、slice1 が、slice とは異なる基になる配列を指すようになったということを意味します。したがって、スライス 1 にその後加えられた変更はスライスには影響せず、その逆も同様です。

結論

スライスは一般にポインタと間違われる可能性がありますが、実際には別個の値です。種類。この本質的な違いは、append() 操作中に現れます。スライス 1 = append(slice1, 100) などの代入により、元のスライスと同じ基になる配列を指す場合とそうでない場合がある、新しいスライス ヘッダーが作成されます。これは、Go コードでスライスを操作するときに留意することが重要です。

以上がGo の append() オペレーションのスライス動作の背後にある謎は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!