2016-04-27 4 views
1
anotherSlice := theSlice 
anotherSlice = append(anotherSlice, newEle) 
fmt.Println(len(anotherSlice) == len(theSlice)) 

このスニペットはfalseを出力します。どうして?参照型 "slice"の変数を別の変数に代入すると、同時に変更しないのはなぜですか?

package main 

import "fmt" 

func main() { 
    theSlice := []int{3,3,2,5,12,43} 
    anotherSlice := theSlice 
    fmt.Println(anotherSlice[3], theSlice[3]) 
    anotherSlice[3] = anotherSlice[3]+2 
    fmt.Println(anotherSlice[3], theSlice[3]) 
    anotherSlice = append(anotherSlice[:3], anotherSlice[4:]...) 
    fmt.Println(len(anotherSlice),len(theSlice)) 
} 

出力は以下のようなものです::

そしてここでは、他のいくつかの実験である

追加スライス anotherSliceは、新しい要素のための能力を持っていないときはいつでも
5 5 
7 7 
5 6 

Program exited. 

答えて

2

append機能は、新しいスライスとリターンを作成しますそれ。それ以来、スライスanotherSlicetheSliceは異なります。スライスは別々のアレイによってバックアップされています。

短い長さのスライスの再スライスanotherSlice[:3]は、スライスの元の容量に影響を与えません。

次の行:第

anotherSlice = append(anotherSlice[:3], anotherSlice[4:]...) 

カットアウト(指標3)要素。 anotherSlice[:3]はすべての要素を保持する容量がanotherSlice[4:]であるため、新しい割り当ては行われないため、両方のスライスが変更されます。

package main 

import (
     "fmt" 
) 

func main() { 
     x := []int{1, 2, 3, 4, 5, 6} 
     fmt.Println(cap(x[:3]) >= len(x[:3])+len(x[4:])) 
     y := append(x[:3], x[4:]...) 
     fmt.Println(x, y) 
} 

Playground

+0

私は長さを縮めるために何かを試しました、プロセスはポストで更新されます。それは収縮後、anotherSliceも容量を5に縮小したからですか? –

1

1つのスライスの長さは、他のスライスの長さの変化への変化に追従しない理由に答えがあります基礎となるストレージpには関係しない一時的にコピーおよび/または修正される。

Goでは、スライスが何であるかを覚えておくことが重要です。これは、長さフィールド、容量フィールド、および配列へのポインタを持つ構造体です。一部の操作 長さフィールドを変更します。いくつかは容量フィールドを変更します。いくつかは、基になる配列に格納されているデータを変更します。

言語でスライスがどのように実装されているか把握できない場合は、あらゆる種類の混乱とバグがあり、機会が無駄になります。スライスがどのように実装されているかに慣れれば、非常に使いやすくなり、コンパイラがスライスの構造を理解し、非常にエレガントで読みやすいコードを書くことができるという事実が書かれます。

関連する問題