ホームページ >バックエンド開発 >Golang >Go で `append(x, x...)` がスライスを新しいバッキング配列にコピーするのはなぜですか?

Go で `append(x, x...)` がスライスを新しいバッキング配列にコピーするのはなぜですか?

PHPz
PHPz転載
2024-02-10 11:12:231008ブラウズ

为什么 `append(x, x...)` 将切片复制到 Go 中的新支持数组中?

php エディターの Youzi が、誰にとってもよくある質問に答えます。「append(x, x...)」はなぜ Go の新しいサポート配列にスライスをコピーするのですか? Go プログラミング言語では、要素をスライスに追加するために「append」関数が使用されます。 「append」関数を使用するとき、スライスの容量が不十分な場合、Go は新しい基になる配列を作成し、元のスライスの要素を新しい基になる配列にコピーします。これは、Go ではスライスは動的配列への参照であるため、スライスの容量が十分でない場合は、より多くの要素を収容するために新しい配列を作成する必要があります。このメカニズムにより、スライスの連続性とスケーラビリティが保証されますが、パフォーマンスの低下も引き起こします。

質問内容

go のスライス ヒント wiki や go ライブラリ (この例など) では、スライスを新しいバッキング配列の中央にコピーするための次のようなコードが表示されることがあります。

リーリー

私が理解していると思うことは次のとおりです:

  • append の 2 番目の引数としてスライス内のすべての項目が新しいバッキング配列にコピーされます。
  • append の最初のパラメータでは、コードは完全なスライス式を使用します。 (最初のパラメータを a[0:0:0] に書き換えることもできますが、省略した場合は、最初の 0 が提供されます。これは、ここでのより一貫性があると思います。意味は関係ありません。)
  • 仕様によれば、生成されるスライスは元のスライスと同じタイプであり、長さと容量はゼロである必要があります。
  • (これも直接関係ありませんが、append の代わりに copy を使用すると、よりわかりやすくなります。)

ただし、構文 append(someslice[:0:0], someslice...) が新しいバッキング配列を作成する理由がまだよくわかりません。私も最初は、なぜ append 操作で元のスライスが台無しにされない (または切り捨てられない) のかについて混乱しました。

今の私の推測:

  • newslice := oldslice を割り当てるだけで、一方への変更がもう一方にも反映されるため、これらはすべて必要かつ有用であると思います。通常、これは望ましくありません。
  • append の結果を元のスライスに代入していないため (これは Go では正常です)、元のスライスには何も起こりません。切り捨てられたり、変更されたりすることはありません。
  • anyslice[:0:0] の長さと容量はゼロなので、Go が anyslice の要素を結果に割り当てたい場合は、新しいサポートを作成する必要があります配列。これは新しいバッキング配列を作成する 理由ですか?
  • anyslice... に要素がない場合はどうなりますか? Go プレイグラウンドのスニペットは、空のスライスでこの追加のトリックを使用すると、コピーとオリジナルが最初は同じバッキング配列を持つことを示しています。 (編集: コメント投稿者が説明したように、私はスニペットを誤解しました。スニペットは、両方の項目が最初は同じであることを示していますが、どちらも配列をサポートしていません。両方ともオリジナルがユニバーサルであることを示しています両方のスライスの長さと容量がゼロであるため、いずれかのスライスに何かを追加すると、そのスライスは新しいバッキング配列を取得します。ですので、効果は今も同じだと思います。つまり、append コピー後、2 つのスライスは相互に影響を与えることはできません。
  • この他のプレイグラウンド スニペットは、スライスに 0 個以上の要素がある場合、append copy メソッドが新しいバッキング配列を直ちに生成することを示しています。この場合、結果として得られる 2 つのスライスは、いわばすぐに分離されます。

これについてはおそらく過度に心配していますが、 理由 append(a[:0:0], a...) についてもっと詳しく説明していただきたいです。トリックワークスもそうです。

解決策

anySlice[:0:0] の長さと容量はゼロであるため、Go が anySlice の要素を結果に割り当てたい場合は、新しいバッキング配列を作成する必要があります。これが新しいバッキング配列が作成された理由ですか?

容量は 0 なので、そうです。

https://pkg.go.dev/[email protected]#追加

十分な容量がある場合は、新しい要素を収容するためにターゲットが再スライスされます。そうでない場合は、新しい基になる配列が割り当てられます。

  • cap=0 は空でないスライスには不十分です。新しい配列を割り当てる必要があります。

以上がGo で `append(x, x...)` がスライスを新しいバッキング配列にコピーするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。