slices 标准库(1.21+)
本教程共 80 篇 · 第 31 篇 · 更新于 2026-07-27 · 约 7 分钟阅读
31. slices 标准库(1.21+)
本节目标:学会用 Go 1.21 新增的 slices 标准库,一行代码搞定排序、查找、克隆、反转等常见操作。
为什么需要 slices 包
在 Go 1.21 之前,给切片排序要用 sort 包,写起来挺啰嗦的。查找元素得自己写循环,克隆切片得用 copy。Go 1.21 终于把这些常用操作收进了标准库,包名就叫 slices。
Note
slices包是 Go 1.21(2023 年 8 月)引入的。如果你用的 Go 版本低于 1.21,需要先升级。
排序:slices.Sort
Sort 对切片做升序排序,直接修改原切片:
package main
import (
"fmt"
"slices"
)
func main() {
s := []int{3, 1, 4, 1, 5, 9, 2, 6}
slices.Sort(s)
fmt.Println(s) // [1 1 2 3 4 5 6 9]
}
如果想降序排,排完反转一下就行:
slices.Sort(s)
slices.Reverse(s)
fmt.Println(s) // [9 6 5 4 3 2 1 1]
Sort 要求元素是可排序的类型(实现了 cmp.Ordered 约束,包括数字和字符串)。如果你要排自定义结构体,用 SortFunc:
package main
import (
"cmp"
"fmt"
"slices"
)
type Person struct {
Name string
Age int
}
func main() {
people := []Person{
{"Alice", 30},
{"Bob", 25},
{"Charlie", 35},
}
slices.SortFunc(people, func(a, b Person) int {
return cmp.Compare(a.Age, b.Age)
})
fmt.Println(people)
// [{Bob 25} {Alice 30} {Charlie 35}]
}
SortFunc 接收一个比较函数,返回负数表示 a 在前,正数表示 b 在前,0 表示相等。cmp.Compare 是 Go 1.21 新增的工具函数,帮你写比较逻辑。
查找:slices.Contains 和 slices.Index
Contains 判断切片里有没有某个值:
s := []int{1, 2, 3, 4, 5}
fmt.Println(slices.Contains(s, 3)) // true
fmt.Println(slices.Contains(s, 6)) // false
Index 返回第一个匹配元素的下标,找不到返回 -1:
s := []string{"apple", "banana", "cherry"}
fmt.Println(slices.Index(s, "banana")) // 1
fmt.Println(slices.Index(s, "grape")) // -1
TipGo 1.21 之前,查找元素你得自己写 for 循环。现在一行函数调用搞定,代码清爽多了。
克隆:slices.Clone
Clone 创建一个底层数组独立的副本:
s := []int{1, 2, 3}
cloned := slices.Clone(s)
cloned[0] = 100
fmt.Println(s) // [1 2 3] 原切片没变
fmt.Println(cloned) // [100 2 3]
等价于 append([]T(nil), s...),但用 Clone 更直观。
反转:slices.Reverse
Reverse 原地反转切片:
s := []int{1, 2, 3, 4, 5}
slices.Reverse(s)
fmt.Println(s) // [5 4 3 2 1]
二分查找:slices.BinarySearch
如果切片已经排好序了,用二分查找比遍历快得多:
s := []int{1, 3, 5, 7, 9, 11}
pos, found := slices.BinarySearch(s, 7)
fmt.Println(pos, found) // 3 true
pos, found = slices.BinarySearch(s, 8)
fmt.Println(pos, found) // 4 false
返回两个值:找到的话是下标和 true,没找到的话是「应该插入的位置」和 false。
其他常用函数
slices 包还有不少好用的函数,列几个常见的:
| 函数 | 作用 |
|---|---|
slices.Min(s) | 返回最小值 |
slices.Max(s) | 返回最大值 |
slices.Equal(a, b) | 比较两个切片是否相等 |
slices.Delete(s, i, j) | 删除下标 i 到 j 的元素 |
slices.Insert(s, i, v...) | 在下标 i 处插入元素 |
slices.Compact(s) | 去掉连续重复的元素 |
slices.Grow(s, n) | 预留 n 个元素的容量 |
slices.IsSorted(s) | 判断是否已排序 |
来个 Insert 和 Delete 的例子:
package main
import (
"fmt"
"slices"
)
func main() {
s := []int{1, 2, 4, 5}
// 在下标2处插入3
s = slices.Insert(s, 2, 3)
fmt.Println(s) // [1 2 3 4 5]
// 删除下标1到3(不含3)的元素
s = slices.Delete(s, 1, 3)
fmt.Println(s) // [1 4 5]
}
以前自己写 append 拼接来删除元素,现在直接调 Delete,省心多了。
Warning
slices.Sort和slices.Reverse会直接修改原切片,不会返回新的。如果你不想动原切片,先Clone再操作。
小结
slices 标准库把以前手写的切片操作全收编了:
- 排序用
Sort/SortFunc - 查找用
Contains/Index/BinarySearch - 复制用
Clone - 增删用
Insert/Delete - 反转用
Reverse
从 Go 1.21 开始,写切片操作代码再也不用造轮子了。下一部分我们进入 map 的世界。