以下程序有意外输出。
func main(){
s:=[]int{5}
s=append(s,7)
s=append(s,9)
x:=append(s,11)
y:=append(s,12)
fmt.Println(s,x,y)
}
输出:[5 7 9] [5 7 9 12] [5 7 9 12]
为什么x
12
的最后一个元素?
答案 0 :(得分:11)
切片只是部分数组的窗口,没有特定的存储空间。
这意味着如果在阵列的同一部分上有两个切片,则两个切片必须“包含”相同的值。
以下是这里发生的事情:
append
时,您会在大小为2
的基础数组上获得一个大小为2
的新切片。append
时,您将获得一个大小为3
的新切片,但基础数组的大小为4
(append
通常会分配比立即需要一个,这样就不需要在每次追加时分配。)append
不需要新数组。因此x
和y
都将使用与先前切片s
相同的基础数组。你在这个数组的同一个插槽中写11
然后12
,即使你得到两个不同的切片(记住,它们只是窗口)。您可以通过在每次追加后打印切片的容量来检查:
fmt.Println(cap(s))
如果您想在x
和y
中使用不同的值,则应该执行copy,例如:
s := []int{5}
s = append(s, 7)
s = append(s, 9)
x := make([]int,len(s))
copy(x,s)
x = append(x, 11)
y := append(s, 12)
fmt.Println(s, x, y)
这里的另一个解决方案可能是强制s
切片后面的数组容量不大于所需的容量(从而确保后面的两个append
具有使用新数组):
s := []int{5}
s = append(s, 7)
s = append(s, 9)
s = s[0:len(s):len(s)]
x := append(s, 11)
y := append(s, 12)
fmt.Println(s, x, y)
答案 1 :(得分:1)
dystroy解释得非常好。我想为行为添加一个视觉解释。
切片只是数组段的描述符。它由一个指向数组的指针(ptr),段的长度(len)和容量(cap)组成。
+-----+
| ptr |
|*Elem|
+-----+
| len |
|int |
+-----+
| cap |
|int |
+-----+
因此,代码的解释如下;
func main() {
+
|
s := []int{5} | s -> +-----+
| []int | ptr +-----> +---+
| |*int | [1]int| 5 |
| +-----+ +---+
| |len=1|
| |int |
| +-----+
| |cap=1|
| |int |
| +-----+
|
s = append(s,7) | s -> +-----+
| []int | ptr +-----> +---+---+
| |*int | [2]int| 5 | 7 |
| +-----+ +---+---+
| |len=2|
| |int |
| +-----+
| |cap=2|
| |int |
| +-----+
|
s = append(s,9) | s -> +-----+
| []int | ptr +-----> +---+---+---+---+
| |*int | [4]int| 5 | 7 | 9 | |
| +-----+ +---+---+---+---+
| |len=3|
| |int |
| +-----+
| |cap=4|
| |int |
| +-----+
|
x := append(s,11) | +-------------+-----> +---+---+---+---+
| | | [4]int| 5 | 7 | 9 |11 |
| | | +---+---+---+---+
| s -> +--+--+ x -> +--+--+
| []int | ptr | []int | ptr |
| |*int | |*int |
| +-----+ +-----+
| |len=3| |len=4|
| |int | |int |
| +-----+ +-----+
| |cap=4| |cap=4|
| |int | |int |
| +-----+ +-----+
|
y := append(s,12) | +-----> +---+---+---+---+
| | [4]int| 5 | 7 | 9 |12 |
| | +---+---+---+---+
| |
| +-------------+-------------+
| | | |
| s -> +--+--+ x -> +--+--+ y -> +--+--+
| []int | ptr | []int | ptr | []int | ptr |
| |*int | |*int | |*int |
| +-----+ +-----+ +-----+
| |len=3| |len=4| |len=4|
| |int | |int | |int |
| +-----+ +-----+ +-----+
| |cap=4| |cap=4| |cap=4|
| |int | |int | |int |
+ +-----+ +-----+ +-----+
fmt.Println(s,x,y)
}