切片是动态数组,容量是根据元素动态增加的。
本来想看看源码怎么写的,发现切片追加元素的方法是内置的,看起来还挺麻烦
源码位于 builtin.go
中:
go
// 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
那么,就用简单的方法来推算规则。编写下面的单测代码,循环 100 次,每次追加 1个元素,看看切片的长度和容量的变化规律是什么。
go
func TestSliceAppend(t *testing.T) {
slice := make([]int, 0)
t.Logf("len:%d cap:%d slice:%v", len(slice), cap(slice), slice)
for i := 0; i < 100; i++ {
slice = append(slice, i)
t.Logf("len:%d cap:%d slice:%v", len(slice), cap(slice), slice)
}
}
输出结果:
slice_test.go:54: len:0 cap:0 slice:[]
slice_test.go:57: len:1 cap:1 slice:[0]
slice_test.go:57: len:2 cap:2 slice:[0 1]
slice_test.go:57: len:3 cap:4 slice:[0 1 2]
slice_test.go:57: len:4 cap:4 slice:[0 1 2 3]
slice_test.go:57: len:5 cap:8 slice:[0 1 2 3 4]
slice_test.go:57: len:6 cap:8 slice:[0 1 2 3 4 5]
slice_test.go:57: len:7 cap:8 slice:[0 1 2 3 4 5 6]
slice_test.go:57: len:8 cap:8 slice:[0 1 2 3 4 5 6 7]
slice_test.go:57: len:9 cap:16 slice:[0 1 2 3 4 5 6 7 8]
slice_test.go:57: len:10 cap:16 slice:[0 1 2 3 4 5 6 7 8 9]
slice_test.go:57: len:11 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10]
slice_test.go:57: len:12 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11]
slice_test.go:57: len:13 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12]
slice_test.go:57: len:14 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13]
slice_test.go:57: len:15 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
slice_test.go:57: len:16 cap:16 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
slice_test.go:57: len:17 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
slice_test.go:57: len:18 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
slice_test.go:57: len:19 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18]
slice_test.go:57: len:20 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
slice_test.go:57: len:21 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
slice_test.go:57: len:22 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21]
slice_test.go:57: len:23 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22]
slice_test.go:57: len:24 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
slice_test.go:57: len:25 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]
slice_test.go:57: len:26 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25]
slice_test.go:57: len:27 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26]
slice_test.go:57: len:28 cap:32 slice:[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27]
...
这里没有都粘贴过来,容量的规则是每次是原来的 2 倍。
Over!