var s []byte
s = make([]byte, 5, 5)
// s == []byte{0, 0, 0, 0, 0}
当容量参数被忽略时,它默认为指定的长度。下面是简洁的写法:
s := make([]byte, 5)
可以使用内置函数 len 和 cap 获取切片的长度和容量信息。
len(s) == 5
cap(s) == 5
接下来的两个小节将讨论长度和容量之间的关系。
切片的零值为 nil 。对于切片的零值, len 和 cap 都将返回0。
切片也可以基于现有的切片或数组生成。切分的范围由两个由冒号分割的索引对应的半开区间指定。 例如,表达式 b[1:4] 创建的切片引用数组 b 的第1到3个元素空间(对应切片的索引为0到2)。
b := []byte{'g', 'o', 'l', 'a', 'n', 'g'}
// b[1:4] == []byte{'o', 'l', 'a'}, sharing the same storage as b
切片的开始和结束的索引都是可选的;它们分别默认为零和数组的长度。
// b[:2] == []byte{'g', 'o'}
// b[2:] == []byte{'l', 'a', 'n', 'g'}
// b[:] == b
下面语法也是基于数组创建一个切片:
x := [3]string{"Лайка", "Белка", "Стрелка"}
s := x[:] // a slice referencing the storage of x
切片的内幕
一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度, 和容量(片段的最大长度)。

前面使用 make([]byte, 5) 创建的切片变量 s 的结构如下:

长度是切片引用的元素数目。容量是底层数组的元素数目(从切片指针开始)。 关于长度和容量和区域将在下一个例子说明。
我们继续对 s 进行切片,观察切片的数据结构和它引用的底层数组:
s = s[2:4]

切片操作并不复制切片指向的元素。它创建一个新的切片并复用原来切片的底层数组。 这使得切片操作和数组索引一样高效。因此,通过一个新切片修改元素会影响到原始切片的对应元素。
d := []byte{'r', 'o', 'a', 'd'}
e := d[2:]
// e == []byte{'a', 'd'}
e[1] = 'm'
// e == []byte{'a', 'm'}
// d == []byte{'r', 'o', 'a', 'm'}
前面创建的切片 s 长度小于它的容量。我们可以增长切片的长度为它的容量:
s = s[:cap(s)]

切片增长不能超出其容量。增长超出切片容量将会导致运行时异常,就像切片或数组的索引超 出范围引起异常一样。同样,不能使用小于零的索引去访问切片之前的元素。









