Go语言之切片的原理与用法 - 《Go语言实战指南》

有没有人在啊,想请教下,Go语言之切片的原理与用法 - 《Go语言实战指南》
最新回答
旧我

2026-10-17 12:15:25

Go语言中的切片(slice)是一种动态数组,它提供了比数组更灵活、高效的数据处理能力。以下是关于切片原理与用法的详细说明:

一、什么是切片

切片是对数组的一个连续片段的引用,其本质是一个三元组:

  • 指向底层数组的指针:指向切片所引用的数组的起始位置。
  • 切片的长度(len):切片中当前包含的元素数量。
  • 切片的容量(cap):从切片的起始位置到底层数组末尾的元素数量。
二、切片的声明与初始化
  1. 从数组或切片派生:

    arr := [5]int{1, 2, 3, 4, 5}s1 := arr[1:4] // 包含索引1到3,不包含4fmt.Println(s1) // [2 3 4]
  2. 使用make:

    s2 := make([]int, 3, 5) // 长度为3,容量为5fmt.Println(s2) // [0 0 0]
  3. 使用字面量:

    s3 := []string{"go", "java", "rust"}
三、切片的基本操作
  1. 访问元素:

    s := []int{10, 20, 30}fmt.Println(s[1]) // 20
  2. 修改元素:

    s[1] = 99
  3. 遍历切片:

    for i, v := range s { fmt.Printf("Index %d: %dn", i, v)}
四、切片的长度与容量s := []int{1, 2, 3, 4, 5}sub := s[1:3]fmt.Println(len(sub)) // 2fmt.Println(cap(sub)) // 4(从索引1到数组末尾)五、切片的扩容

当切片容量不足时,使用append会自动扩容:

s := []int{1, 2}s = append(s, 3, 4, 5)fmt.Println(s) // [1 2 3 4 5]

注意:append可能导致切片指向新的底层数组。

六、切片之间的共享与副本

多个切片可能共享同一个底层数组:

arr := [5]int{1, 2, 3, 4, 5}s1 := arr[1:4]s2 := arr[2:5]s1[1] = 99fmt.Println(arr) // [1 2 99 4 5]fmt.Println(s2) // [99 4 5]

如果需要独立副本,可使用copy:

dst := make([]int, len(s1))copy(dst, s1)七、切片是引用类型

函数传参时,修改切片会影响原始数据(因为底层数组是共享的):

func modify(s []int) { s[0] = 100}a := []int{1, 2, 3}modify(a)fmt.Println(a) // [100 2 3]八、删除切片元素

Go没有内建删除函数,可以用切片拼接模拟:

s := []int{1, 2, 3, 4, 5}i := 2 // 删除索引为2的元素s = append(s[:i], s[i+1:]...)fmt.Println(s) // [1 2 4 5]九、切片陷阱:共享底层数组导致意外修改s1 := []int{1, 2, 3, 4}s2 := s1[:2]s3 := append(s2, 99, 100) // 此时可能会影响 s1 的内容

使用copy()复制切片是解决此问题的安全做法。

十、小结
  • 特性说明:

    动态长度:可根据需要自动扩容。

    引用类型:多个切片可能共享底层数组。

    三元结构:指针 + 长度 + 容量。

  • 用途广泛:是数组的增强版,常用于集合处理。
  • 可组合使用:和append、copy、range搭配使用最常见。

切片的灵活性和效率让它成为Go语言中处理数据集合的首选结构。理解其底层原理能帮助你写出更高性能的代码。