Golang 的数组是长度固定的, 一旦声明其长度就无法修改.

切片为数组操作提供了一定的灵活性.

切片本质上是对数组的封装, 把数组的一部分暴露出来. 切片是可变的.

切片包含长度和容量的概念, 长度内的空间是可以直接赋值操作的; 长度以外, 容量以内的, 不能直接赋值, 但可以通过 append 方法来使用容量.

package main

import "fmt"

func main() {
	arr := [10]int{1, 2, 3, 4, 5, 6, 7, 9, 10}
	slice := arr[2:5:6]

	slice = append(slice, 100)
	slice = append(slice, 101)
	slice = append(slice, 102)

	fmt.Println(arr, slice)
}

对于一个长度为 l 的数组 arr, slice := arr[i:j:k] 表示从 arr 中切片出 slice, 长度从i到j, 包括i不包括j; 容量从i到k, 包括i不包括k. k 是可选的, k 默认跟 l 相等, 即容量直到数组的结尾(包含最后一个元素).

例如: arr 是一个长度为 10 的数组, 它的长度是不可修改的. slice := arr[2:5:6], slice 从 arr 中切片出来, 新的切片包含从第 2 个元素到第 5 个元素, 长度为 3, 容量为从第 2 个元素到第 6 个元素, 容量为 4 .

切片的 append 方法, 把新元素追加到长度之后的容量位置. slice := arr[2:5:6] 本身是 [3, 4, 5], 长度为3, 容量为 4, append 100 后, 把剩余的一个容量占满, 也就是 [3, 4, 5, 100]. 特别注意, 这里的 100 占用的是原底层数组的空间, 这个修改会影响到 arr, arr 的 6 被修改为了 100.

当 append 101 的时候, 容量已经满了, 这时候切片会自己去申请新的空间来存放 101. arr 的 7 不会被修改.

当切片的容量在 1000 以下时, 切片只能扩展是容量翻倍; 当切片的容量在 1000 以上的时候, 新容量是原来的 1.25 倍.

append 102 被安排在新的已经扩展的容量内.

所以, 上面 DEMO 的 outputs:

[1 2 3 100 5] [3 100 101 102]