切片基本操作
使用下面的代码可创建一个切片字面量:
aSliceLiteral := []int{1, 2, 3, 4, 5}
与定义数组相比,切片字面量只是没有指定元素数量。如果你在[]中填入数字,你将得到的是数组。
也可以使用make()创建一个空切片,并指定切片的长度和容量。容量这个参数可以省略,在这种情况下容量等于长度。
下面定义一个长度和容量均为20的空切片,并且在其需要的时候会自动扩容:
integer := make([]int, 20)
Go自动将空切片的元素初始化为对应元素的零值,意味着切片初始化时的值是由切片类型决定的。
使用下面的代码遍历切片中的元素:
for i :=0; i < len(integer); i++ {
fmt.Println(i)
}
切片变量的零值是nil, 下面代码可将已有的切片置为空:
aSliceLiteral = nil
可以使用append()函数追加元素到切片,此操作将触发切片自动扩容。
integer = append(integer, -5900)
integer[0]代表切片integer的第一个元素,integer[len(integer)-1]代表最后一个元素。
同时,使用[:]操作可以获取连续多个元素,下面的代码表示获取第2、3个元素:
integer[1:3]
[:]操作也可以帮助你从现有的切片或数组中创建新的切片或数组:
s2 := integer[1:3]
这种操作叫做re-slicing,在某种情况下可能会导致bug:
package main
import “fmt”
func main() {
s1 := make([]int, 5)
reSlice := s1[1:3]
fmt.Println(s1)
fmt.Println(reSlice)
reSlice[0] = -100
reSlice[1] = 123456
fmt.Println(s1)
fmt.Println(reSlice)
}
我们使用[:]操作获取第2、3个元素。
假设有一个数组a1,你可以执行
s1 := a1[:]
来创建一个以a1为引用的切片
将上述代码保存为reslice.go并执行,将得到以下输出;
$ go run reslice.go
[0 0 0 0 0]
[0 0]
[0 -100 123456 0 0 ]
[-100 123456]
可以看到切片s1的输出是[0 -100 123456 0 0 ],但是我们并没有直接改变s1。这说明通过re-slicing操作得到的切片,与原切片指向同一片内存地址!
re-slicing操作的第二个问题是,尽管你可能是想通过使用re-slicing从原切片中得到较小的一个切片,但是原切片的底层数组仍然会跟随着re-slicing得到的小切片,这对于小切片来说并不是什么严重问题,但是在这种情况下就可能导致bug:你将大文件的内容读到切片中,但是你只是想使用其中一小部分。