package main
import "fmt"
func main() {
s := []int{5}
s = append(s, 8)
s = append(s, 9)
x := append(s, 11)
y := append(s, 12)
fmt.Println(s, x, y)
}
以上代码会输出结果
[5 8 9] [5 8 9 12] [5 8 9 12]
结果中 x 被 y 覆盖了
原因是 slice 的容量增长
func main() {
s := []int{5}
fmt.Println("capacity:", cap(s))
s = append(s, 8)
fmt.Println("capacity:", cap(s))
s = append(s, 9)
fmt.Println("capacity:", cap(s))
x := append(s, 11)
fmt.Println("x s capacity:", cap(s))
y := append(s, 12)
fmt.Println("y s capacity:", cap(s))
fmt.Println(s, x, y)
}
逐一打印总容量后发现s的容量增长记录
capacity: 1
capacity: 2
capacity: 4
x s capacity: 4
y s capacity: 4
s 当增长到4时因没有新元素计入不再增长
而 x 则是在原本 s 索引 [3] 的地方修改为了 11
y 则是在原本 s 索引 [3] 的地方修改为了 12
但为什么 12 会把 11 覆盖了呢
执行以下代码后发现,三个切片里的各元素的地址一致
func main() {
s := []int{5}
s = append(s, 8)
s = append(s, 9)
fmt.Println(&s[0], &s[1], &s[2])
x := append(s, 11)
fmt.Println(&x[0], &x[1], &x[2], &x[3])
y := append(s, 12)
fmt.Println(&y[0], &y[1], &y[2], &y[3])
}
输出结果后
0xc0000a8140 0xc0000a8148 0xc0000a8150
0xc0000a8140 0xc0000a8148 0xc0000a8150 0xc0000a8158
0xc0000a8140 0xc0000a8148 0xc0000a8150 0xc0000a8158
查看 append 源码
// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
// slice = append(slice, elem1, elem2)
// slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
// slice = append([]byte("hello "), "world"...)
func append(slice []Type, elems ...Type) []Type
源码里表示,“如果原切片拥有足够的容量时,目标会重新切片并容纳新元素”。
也就是说返回的还是 s 本身的副本(指向地址都是一样的),而不是新的切片。
只有当 cap 超出最大时才会返回一个新的切片(指向地址都不一样)。
func main() {
s := []int{5}
s = append(s, 8)
s = append(s, 9)
x := append(s, 11)
fmt.Println(&x[0], &x[1], &x[2], &x[3])
fmt.Println("x capacity:", cap(x))
y := append(s, 12, 13)
fmt.Println(&y[0], &y[1], &y[2], &y[3], &y[4])
fmt.Println("y capacity:", cap(y))
}
输出结果
0xc00000e3e0 0xc00000e3e8 0xc00000e3f0 0xc00000e3f8
x capacity: 4
0xc000010240 0xc000010248 0xc000010250 0xc000010258 0xc000010260
y capacity: 8