Skip to content

Go 语言笔记:切片

切片的概念

切片和数组一样都是序列,但切片是变长的,因此切片声明时一般写作 []Type ,切片是对数组的引用,也就是说切片会将数组作为其底层的数据结构,可以时数组由某个索引开始到另一个索引终止对一段连续片段。

切片的创建

使用 []Type 创建切片

go
// 声明整形类型的切片
var nums []int

// 声明空切片
var nums = []int{}

// 初始化一个非空切片
var slice = []int{1, 8}

// 截取数组获得切片
arr := [5]int{10, 20, 30, 40}
var nums = arr[1:2]
fmt.Println(nums) // [20 30]

使用语法 arr[start:end] 是创建一个从数组 arr 索引 start 开始到 end - 1 结束的切片,左开右闭。除此之外,我们也可以使用 make 函数创建 一个切片,格式为 make([]type, size, cap)

go
// 创建一个长度为2,容量为3的整形切片
nums := make([]int, 2, 3)

切片的长度和容量

切片的组成部分为:指针、长度和容量,指针指向切片第一个元素对应的底层数组元素的地址,长度对应切片中元素的个数,容量是从切片的开始位置到底层数据的结束位置,且长度不能超容量。我们可以使用内置的 lencap 函数分别获取切片的长度和容量。

go
arr := [5]int{10, 20, 30, 40}
var nums = arr[1:2]
fmt.Println(len(nums)) // 1
fmt.Println(cap(nums)) // 3

切片和数组不同,切片是引用类型,因此其默认值为 nil

go
var nums []int
fmt.Println(nums == nil) // true

但一个切片中的元素为空时,应该判断其长度是否为 0 作为一个空切片的判断依据。切片之间不能直接比较,必须对切片中的每个元素进行比较来判断两个切片是否相等,标准库中针对字节类型的切片([]byte)是否相等提供了 bytes.Equal 函数。

切片的修改

切片本身不拥有任何数据,它只是底层数组的一种表示方式,对切片的任何修改都会反应到底层数据中。

go
arr := [5]int{10, 20, 30, 40}
var nums = arr[1:3]
fmt.Println(arr)      // [10 20 30 40]
fmt.Println(nums)     // [20 30]

// 修改切片
nums[0] = 50
fmt.Println(arr)      // [10 50 30 40]
fmt.Println(nums)     // [50 30]

切片追加元素

使用 append 函数可以将新的元素追加到切片上,当新的元素加入到切片之后,会创建一个新的数组,现有数组的元素被复制到这个新的数组中,并返回这个新数组的新切片引用,如果追加后长度超过旧切片的长度时,新切片的容量会变成旧切片容量的两倍。

go
nums := []int{1, 2}
fmt.Println(cap(nums))  // 2

// 追加一个元素 3
nums = append(nums, 3)
fmt.Println(cap(nums))  // 4

// 追加两个元素 4 5
nums = append(nums, 4, 5)
fmt.Println(cap(nums))  // 8

// 追加一个切片 ... 表示解包不能省略
nums = append(nums, []int{6, 7}...)
fmt.Println(cap(nums))  // 8


// 在第一个位置插入一个元素 0
nums = append([]int{0}, nums...)
fmt.Println(cap(nums))  // 8

nums = append(nums, 9)
fmt.Println(cap(nums))  // 16
fmt.Println(nums)       // [0 1 2 3 4 5 6 7 9]

获取切片元素

和数组一样,我们也可以使用 for range 循环来获取切片 的索引和索引对应的值

go
nums := []int{1, 2, 3, 4, 5}
for idnex, value := range nums {
  fmt.Printf("nums[%d] = %d\n", index, value)
}

多维切片

go
nums := [][]string {{"a", "A"}, {"b", "B"}, {"c", "C"}}
fmt.Println(cap(nums))  // 3
fmt.Println(len(nums))  // 3

Released under the MIT License.