02.Slice 切片
切片(Slice)是 Go 语言中比数组更为灵活和强大的数据结构。切片本质上是对数组的一个视图,可以动态调整大小。下面详细介绍切片的定义、初始化、操作和使用注意事项。
切片的定义与初始化
切片的定义语法为:[]T
,其中 T
表示切片元素的类型。切片的初始化可以通过数组字面量、内置函数 make
或从现有数组或切片中创建。
示例
package main import "fmt" func main() { // 使用数组字面量初始化切片 slice1 := []int{1, 2, 3, 4, 5} fmt.Println(slice1) // 输出:[1 2 3 4 5] // 使用内置函数 make 初始化切片 slice2 := make([]int, 5) fmt.Println(slice2) // 输出:[0 0 0 0 0] // 从现有数组或切片中创建切片 arr := [5]int{10, 20, 30, 40, 50} slice3 := arr[1:4] // 包含索引 1 到 3 的元素,不包括 4 fmt.Println(slice3) // 输出:[20 30 40] }
切片的基本操作
访问与修改元素
切片的元素访问和修改与数组类似,通过索引进行。
package main import "fmt" func main() { slice := []int{1, 2, 3, 4, 5} fmt.Println(slice[0]) // 输出:1 slice[1] = 20 fmt.Println(slice) // 输出:[1 20 3 4 5] }
获取切片长度和容量
切片的长度通过 len
函数获取,容量通过 cap
函数获取。
package main import "fmt" func main() { slice := []int{1, 2, 3, 4, 5} fmt.Println("Length:", len(slice)) // 输出:Length: 5 fmt.Println("Capacity:", cap(slice)) // 输出:Capacity: 5 }
切片的动态增长
切片的长度可以通过内置函数 append
动态增加。
package main import "fmt" func main() { slice := []int{1, 2, 3} slice = append(slice, 4, 5) fmt.Println(slice) // 输出:[1 2 3 4 5] }
切片的遍历
使用 for
循环或 range
关键字遍历切片。
package main import "fmt" func main() { slice := []int{1, 2, 3, 4, 5} // 使用传统的 for 循环遍历切片 for i := 0; i < len(slice); i++ { fmt.Println(slice[i]) } // 使用 range 关键字遍历切片 for index, value := range slice { fmt.Printf("Index: %d, Value: %d\n", index, value) } }
多维切片
Go 语言支持多维切片。
package main import "fmt" func main() { // 定义一个二维切片 var matrix [][]int // 初始化二维切片 matrix = [][]int{ {1, 2, 3}, {4, 5, 6}, } fmt.Println(matrix) // 输出:[[1 2 3] [4 5 6]] // 访问二维切片元素 fmt.Println(matrix[0][1]) // 输出:2 // 遍历二维切片 for i := 0; i < len(matrix); i++ { for j := 0; j < len(matrix[i]); j++ { fmt.Printf("matrix[%d][%d] = %d\n", i, j, matrix[i][j]) } } }
使用切片应注意的点
slice 可以向后扩展,不可以向前扩展
s[i] 不可以超越 len(s),向后扩展不可以超越底层数组cap(s)
-
切片的零值:切片的零值是
nil
,一个nil
切片的长度和容量都是 0。var slice []int fmt.Println(slice == nil) // 输出:true fmt.Println(len(slice)) // 输出:0 fmt.Println(cap(slice)) // 输出:0
-
共享底层数组:切片是对底层数组的引用,多个切片可以共享同一个底层数组。对一个切片的修改可能影响共享相同底层数组的其他切片。
arr := [5]int{1, 2, 3, 4, 5} slice1 := arr[:] slice2 := arr[2:] slice2[0] = 100 fmt.Println(slice1) // 输出:[1 2 100 4 5] fmt.Println(slice2) // 输出:[100 4 5]
-
使用
append
时的容量增长:如果切片的容量不足以容纳新的元素,append
操作会创建一个新的底层数组,将旧数组的内容复制过去。slice := []int{1, 2, 3} fmt.Printf("Before append: len = %d, cap = %d\n", len(slice), cap(slice)) slice = append(slice, 4, 5) fmt.Printf("After append: len = %d, cap = %d\n", len(slice), cap(slice))
切片的切片:可以对切片再进行切片操作,但新切片仍然引用相同的底层数组。
slice := []int{1, 2, 3, 4, 5} subSlice := slice[1:4] fmt.Println(subSlice) // 输出:[2 3 4]