数组的切片化 #
采用 array[low : high : max]语法基于一个已存在的数组创建切片。这种方式被称为数组的切片化,比如下面代码:
arr := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
sl := arr[3:7:9]
我们基于数组 arr 创建了一个切片 sl,这个切片 sl 在运行时中的表示是这样:
我们看到,基于数组创建的切片,它的起始元素从 low 所标识的下标值开始,切片的长度(len)是 high - low,它的容量是 max - low。而且,由于切片
sl 的底层数组就是数组 arr,对切片 sl 中元素的修改将直接影响数组 arr 变量。比如,如果我们将切片的第一个元素加 10,那么数组 arr 的第四个元素将变为 14:
sl[0] += 10
fmt.Println("arr[3] =", arr[3]) // 14
这样看来,切片好比打开了一个访问与修改数组的“窗口”,通过这个窗口,我们可以直接操作底层数组中的部分元素。这有些类似于我们操作文件之前打开的“文件描述符”(Windows 上称为句柄),通过文件描述符我们可以对底层的真实文件进行相关操作。可以说,切片之于数组就像是文件描述符之于文件。
在 Go 语言中,数组更多是“退居幕后”,承担的是底层存储空间的角色。切片就是数组的“描述符”,也正是因为这一特性,切片才能在函数参数传递时避免较大性能开销。因为我们传递的并不是数组本身,而是数组的“描述符”,而这个描述符的大小是固定的(见上面的三元组结构),无论底层的数组有多大,切片打开的“窗口”长度有多长,它都是不变的。此外,我们在进行数组切片化的时候,通常省略 max,而 max 的默认值为数组的长度。