同じ基礎となる配列を共有している場合、Go スライスに追加しても元のスライスに影響を与えないのはなぜですか?

Barbara Streisand
リリース: 2024-11-15 06:07:02
オリジナル
215 人が閲覧しました

Why doesn't appending to a Go slice affect the original slice when they share the same underlying array?

スライスの追加動作を理解する

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)
}
ログイン後にコピー

期待される出力は、項目のリストです。最初の追加後にスライスの最初の値が 10000 に変更され、2 回目の追加後に 20000 に変更されました。さらに、スライスとスライス 1 の両方が同じ基になる配列を指しているため、スライス内の項目にもこれらの変更が反映されることが期待されます。

しかし、実際の出力は驚くべきものです。

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

最初の出力は、予想どおり、slice1 が最初の要素の値を 10000 に正常に変更したことを示しています。ただし、2 番目の出力は、後続の追加操作とスライス 1 への変更がスライスに影響を与えていないことを示しています。なぜそうなるのでしょうか?

Go の値セマンティクスを理解する

この動作を理解する鍵は、Go の値セマンティクスにあります。 Go では、変数は値によって渡されます。つまり、変数を別の変数に代入すると、値のコピーが作成されます。これはスライスにも当てはまります。

slice1 := スライスを実行すると、スライス ヘッダーのコピーが作成されます。スライス ヘッダーには、長さ、容量、および基礎となる配列へのポインターに関する情報が含まれています。ただし、基になる配列自体はコピーされません。

追加の動作

追加操作を実行すると、新しいスライス ヘッダーが作成され、新しい基になる配列が割り当てられます。 。元のスライスの要素が新しい配列にコピーされ、新しいスライス ヘッダーが返されます。

この例では、slice1 = append(slice1, 100) を実行すると、新しいスライス ヘッダーが作成され、新しい配列には、既存の要素と追加される追加要素のためのスペースが割り当てられます。スライス 1 の要素が新しい配列にコピーされ、新しいスライス ヘッダーがスライス 1 に割り当てられます。

重要なのは、スライスは依然として元の基になる配列を指していることです。そのため、スライス 1 に加えられた変更はスライス 1 に反映されません。スライス.

結論

スライスの追加動作を理解するには、スライスが次のとおりであることを覚えておくことが重要です。値によって渡されます。要素を追加すると、新しいスライス ヘッダーと基になる配列が作成され、元のスライスは影響を受けません。

以上が同じ基礎となる配列を共有している場合、Go スライスに追加しても元のスライスに影響を与えないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート