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 サイトの他の関連記事を参照してください。