ホームページ > バックエンド開発 > Golang > Go スライスをコピーしてもディープ コピーが作成されないのはなぜですか?また、意図しない突然変異を回避するにはどうすればよいですか?

Go スライスをコピーしてもディープ コピーが作成されないのはなぜですか?また、意図しない突然変異を回避するにはどうすればよいですか?

Patricia Arquette
リリース: 2024-11-27 18:38:14
オリジナル
584 人が閲覧しました

Why Does Copying a Go Slice Not Create a Deep Copy, and How Can I Avoid Unintended Mutations?

Go におけるスライスの可変性を理解する

Go では、スライスは、要素の連続シーケンスを格納する動的にサイズ変更される変数です。これは、長さを格納するヘッダー構造と、要素を含む基になる配列へのポインターを使用して実装されます。

次のコード スニペットを考えてみましょう。

func someFunc(A []int) int {
    ...
    tempA := A // copy the slice by value
    ...
    newArr = remove(tempA, i)
    ...
}

func remove(slice []int, s int) []int {
    return append(slice[:s], slice[s+1:]...)
}
ログイン後にコピー

このコードでは、append 関数がtempA スライスを変更するために使用されます。ただし、someFunc 関数が返されると、tempA が A のコピーとして作成されたにもかかわらず、元の A スライスも変更されます。

なぜこれが起こるのですか?

スライスヘッダーは、基礎となる配列とは別のデータ構造です。スライスがコピーされると、基になる配列ではなく、ヘッダーのみがコピーされます。これは、元の A スライスと新しく作成された tempA スライスが両方とも同じ基になる配列を指していることを意味します。

append 関数が呼び出されると、新しいスライスが作成され、tempA スライスの要素が新しいスライス。ただし、A スライスは依然として同じ基になる配列を指しており、その配列には変更された要素が含まれています。

推奨事項

スライスを変更するときに元のスライスの意図しない変異を避けるためコピーする場合は、copy 関数を使用してスライスのディープ コピーを作成する必要があります。 copy 関数は、新しい基になる配列を作成し、そこに要素をコピーします。

コピー関数の使用方法の例は次のとおりです。

tempA := make([]int, len(A))
copy(tempA, A)
ログイン後にコピー

これにより、新しい基になる配列が作成されます。 tempA を作成し、A からそれに要素をコピーします。 tempA に加えられた変更は、元の A スライスには影響しません。

以上がGo スライスをコピーしてもディープ コピーが作成されないのはなぜですか?また、意図しない突然変異を回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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