切片基本操作

使用下面的代码可创建一个切片字面量:

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:你将大文件的内容读到切片中,但是你只是想使用其中一小部分。