在 Go 语言中,切片(slice)是一个非常重要的数据结构,它是对数组的抽象,提供了更灵活、更强大的序列操作能力。切片本身并不存储任何数据,它只是对底层数组的引用,提供了访问数组部分或全部元素的能力。
切片的定义
切片由三个部分组成:
- 指针:指向底层数组中切片开始的元素。
- 长度(length):切片中元素的数量。
- 容量(capacity):从切片的起始位置到底层数组末尾的元素数量。
创建切片
- 通过数组创建切片:
arr := [5]int{1, 2, 3, 4, 5} slice := arr[1:4] // 创建一个包含 arr[1], arr[2], arr[3] 的切片 fmt.Println(slice) // 输出: [2 3 4]
- 直接创建切片:
slice := []int{1, 2, 3, 4, 5} fmt.Println(slice) // 输出: [1 2 3 4 5]
- 使用
make
函数创建切片:slice := make([]int, 5) // 创建一个长度为5,容量为5的切片 fmt.Println(slice) // 输出: [0 0 0 0 0]
切片的操作
- 访问元素:
slice := []int{1, 2, 3, 4, 5} fmt.Println(slice[2]) // 输出: 3
- 修改元素:
slice := []int{1, 2, 3, 4, 5} slice[2] = 10 fmt.Println(slice) // 输出: [1 2 10 4 5]
- 追加元素:
slice := []int{1, 2, 3} slice = append(slice, 4, 5) fmt.Println(slice) // 输出: [1 2 3 4 5]
- 切片的切片:
slice := []int{1, 2, 3, 4, 5} subSlice := slice[1:3] fmt.Println(subSlice) // 输出: [2 3]
- 切片的长度和容量:
slice := []int{1, 2, 3, 4, 5} fmt.Println(len(slice)) // 输出: 5 fmt.Println(cap(slice)) // 输出: 5
- 复制切片:
slice1 := []int{1, 2, 3} slice2 := make([]int, len(slice1)) copy(slice2, slice1) fmt.Println(slice2) // 输出: [1 2 3]
切片的底层数组
切片是对底层数组的引用,因此对切片的修改会影响底层数组,反之亦然。
arr := [5]int{1, 2, 3, 4, 5} slice := arr[1:4] slice[0] = 10 fmt.Println(arr) // 输出: [1 10 3 4 5]
切片的扩容
当切片的容量不足以容纳新元素时,Go 会自动为其分配一个新的底层数组,并将原有元素复制到新数组中。
slice := []int{1, 2, 3} slice = append(slice, 4, 5, 6) fmt.Println(slice) // 输出: [1 2 3 4 5 6]
注意事项
- 切片是引用类型,传递切片时不会复制底层数组,而是共享同一个底层数组。
- 切片的零值是
nil
,表示一个空的切片。
总结
切片是 Go 语言中非常强大且灵活的工具,它提供了对数组的动态视图,使得操作数组变得更加方便。理解切片的底层机制对于编写高效的 Go 代码非常重要。