go学习笔记(9)切片(2)容量

76574743d554ee5a112e3a80051c0d76.png

接着之前的文章梳理go切片中的容量和长度。

容量

切片中的每一个元素都存放在一块连续的内存中,每个切片都有它自己保留的一块内存,它的大小就是切片的容量。

通常切片的容量会比切片的长度要大,当切片容量和切片的长度一致时,若再用 append 向切片中添加新的元素,go运行时会申请一块更大容量的切片进行扩容。

并将原来切片中的元素复制到新的切片中,把新添加的元素放在其后。用新的切片代替原来的切片。原来的切片将被垃圾回收。

在 Go 1.14 中当切片容量小于1024字节时,每次扩容时新切片的容量翻倍;当容量超过1024字节时每次至少在之前容量的基础上扩容25%

cap()

通过内置函数 len() 可以获取切片的长度,类似的通过cap()可以获取切片的容量

切片的容量与长度代码演示:

1
2
3
4
5
6
7
8
9
10
11
12
var x []int
fmt.Println(x, len(x), cap(x))
x = append(x, 1)
fmt.Println(x, len(x), cap(x))
x = append(x, 2)
fmt.Println(x, len(x), cap(x))
x = append(x, 3)
fmt.Println(x, len(x), cap(x))
x = append(x, 4)
fmt.Println(x, len(x), cap(x))
x = append(x, 5)
fmt.Println(x, len(x), cap(x))

输出:

1
2
3
4
5
6
[] 0 0
[1] 1 1
[1 2] 2 2
[1 2 3] 3 4
[1 2 3 4] 4 4
[1 2 3 4 5] 5 8

make()

如果我们知道切片将要存放数据的大小时,最好用内置函数make创建相应容量大小的切片。

创建一个长度和容量都为10的[]int切片

1
x := make([]int, 10)

用上面的方式创建了一个切片后,再用append向切片中追加数据则会将新的数据存放在切片的最末尾,这也好理解,因为此时切片的长度也是10,再添加新的元素相当于第11个元素了。演示如下:

1
2
3
4
x := make([]int, 10)
fmt.Println(x)
x = append(x, 123)
fmt.Println(x)

输出:

1
2
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 123]

如果要make创建的切片的长度和容量不同,可以这样写:

make创建一个长度为5,容量为10的[]int切片

1
2
3
4
x := make([]int, 5, 10)
fmt.Println(x)
x = append(x, 123)
fmt.Println(x)

输出:

1
2
[0 0 0 0 0]
[0 0 0 0 0 123]

因此如果要创建指定容量而长度为0的切片可以这样:

1
x := make([]int, 0, 10)

如果指定的容量小于长度的话,会编译错误。

江达小记