2.5 标准库泛型
Go 1.21 开始,标准库引入了泛型包 slices、maps 和 cmp,替代了之前 golang.org/x/exp/ 下的实验性实现。
slices 包 — 切片操作
搜索与查找
go
import "slices"
nums := []int{3, 1, 4, 1, 5, 9, 2, 6}
// Index — 线性查找(O(n)),不需要切片有序
idx := slices.Index(nums, 4) // 2
idx = slices.Index(nums, 7) // -1
// Contains — 检查是否存在
has5 := slices.Contains(nums, 5) // true
// IndexFunc — 用谓词查找
idx = slices.IndexFunc(nums, func(n int) bool { return n > 5 }) // 4 (值=9)
// BinarySearch — 二分查找(O(log n)),要求切片有序
sorted := []int{1, 2, 3, 4, 5, 6, 7}
idx, found := slices.BinarySearch(sorted, 5) // idx=4, found=true
idx, found = slices.BinarySearch(sorted, 8) // idx=7, found=false排序
go
// Sort — 升序排序
slices.Sort(nums) // [1 1 2 3 4 5 6 9] 原地排序
// SortFunc — 自定义排序逻辑
people := []Person{{"Alice", 30}, {"Bob", 25}, {"Charlie", 35}}
slices.SortFunc(people, func(a, b Person) int {
return cmp.Compare(a.Age, b.Age)
})
// SortStableFunc — 稳定排序
slices.SortStableFunc(people, func(a, b Person) int {
return cmp.Compare(a.Name, b.Name)
})
// IsSorted / IsSortedFunc — 检查是否有序
slices.IsSorted(sorted) // true
// Min / Max — 找最值
min := slices.Min(nums) // 1
max := slices.Max(nums) // 9
// MinFunc / MaxFunc — 自定义比较
youngest := slices.MinFunc(people, func(a, b Person) int {
return cmp.Compare(a.Age, b.Age)
}) // {Bob 25}修改操作
go
// Insert — 在指定位置插入元素
nums = slices.Insert(nums, 2, 10, 20) // [1 1 10 20 2 3 4 5 6 9]
// Delete — 删除区间 [i, j)
nums = slices.Delete(nums, 2, 4) // [1 1 2 3 4 5 6 9]
// Replace — 替换区间
nums = slices.Replace(nums, 0, 2, 8) // [8 2 3 4 5 6 9]
// Compact — 去除相邻重复
nums = slices.Compact([]int{1, 1, 2, 2, 3}) // [1 2 3]
// CompactFunc — 自定义去重
slices.CompactFunc([]string{"a", "A", "b"}, strings.EqualFold) // ["a", "b"]
// Clip — 释放多余容量
nums = slices.Clip(nums) // cap = len
// Grow — 扩容到指定容量
nums = slices.Grow(nums, 100) // 确保 cap >= 100
// Clone — 浅拷贝
dup := slices.Clone(nums) // 新底层数组比较
go
// Equal — 比较两个切片
a := []int{1, 2, 3}
b := []int{1, 2, 3}
equal := slices.Equal(a, b) // true
// EqualFunc — 自定义相等比较
equal = slices.EqualFunc([]string{"hello", "WORLD"}, []string{"HELLO", "world"},
strings.EqualFold) // true
// Compare — 字典序比较
slices.Compare([]int{1, 2}, []int{1, 3}) // -1 (a < b)
slices.Compare([]int{1, 2}, []int{1, 2}) // 0 (a == b)
slices.Compare([]int{1, 3}, []int{1, 2}) // 1 (a > b)
// CompareFunc — 自定义比较
slices.CompareFunc(people1, people2, func(a, b Person) int {
return cmp.Compare(a.Age, b.Age)
})maps 包 — 映射操作
go
import "maps"
m1 := map[string]int{"a": 1, "b": 2}
m2 := map[string]int{"b": 3, "c": 4}
// Clone — 浅拷贝
clone := maps.Clone(m1) // {"a": 1, "b": 2}
// Copy — 将 src 复制到 dst(覆盖已有 key)
maps.Copy(m1, m2) // m1 = {"a": 1, "b": 3, "c": 4}
// DeleteFunc — 按条件删除
maps.DeleteFunc(m1, func(k string, v int) bool {
return v < 3 // 删除值小于 3 的
})
// m1 = {"b": 3, "c": 4}
// Equal — 比较两个 map
maps.Equal(map[string]int{"a": 1}, map[string]int{"a": 1}) // true
// EqualFunc — 自定义值比较
maps.EqualFunc(
map[string][]int{"a": {1, 2}},
map[string][]int{"a": {1, 2}},
slices.Equal[int], // 自定义值的比较函数
) // truecmp 包 — 比较函数
go
import "cmp"
// Compare — 通用比较,返回 -1/0/1
cmp.Compare(1, 2) // -1
cmp.Compare(2, 2) // 0
cmp.Compare(3, 2) // 1
cmp.Compare("a", "b") // -1
cmp.Compare(1.5, 1.5) // 0
// Less — 判断 a < b
cmp.Less(1, 2) // true
cmp.Less(2, 1) // false
// Or — 返回第一个非零值(短路求值)
// 用于链式回退
value := cmp.Or(
getFromCache(), // 优先从缓存取
getFromDB(), // 缓存未命中,从 DB 取
"default", // 都没有返回默认值
)
// 实用模式:超时回退
timeout1 := maybeTimeout1()
timeout2 := maybeTimeout2()
t := cmp.Or(timeout1, timeout2, 30*time.Second)sort 包(Go 1.22+)
Go 1.22 为 sort 包添加了泛型 API,作为 slices.Sort 的补充:
go
import "sort"
// sort.Sort 的逻辑等价于 slices.Sort
nums := []int{3, 1, 4, 1, 5}
sort.Ints(nums) // 原地排序(传统 API)
// 泛型版本更灵活
sort.Slice(nums, func(i, j int) bool { return nums[i] < nums[j] })实战:综合示例
go
package main
import (
"cmp"
"fmt"
"maps"
"slices"
)
func main() {
// 1. 数据清理:去重 + 排序
raw := []int{5, 2, 8, 2, 9, 1, 5, 3}
slices.Sort(raw)
deduped := slices.Compact(raw)
fmt.Println(deduped) // [1 2 3 5 8 9]
// 2. 查找 + 修改
if idx := slices.Index(deduped, 5); idx != -1 {
deduped = slices.Replace(deduped, idx, idx+1, 50)
}
fmt.Println(deduped) // [1 2 3 50 8 9]
// 3. Map 过滤
config := map[string]int{"timeout": 30, "retries": 0, "workers": 4}
maps.DeleteFunc(config, func(k string, v int) bool { return v == 0 })
fmt.Println(config) // map[timeout:30 workers:4]
// 4. 排序 + 分页
large := make([]int, 1000)
for i := range large { large[i] = (i * 7) % 1000 }
slices.Sort(large)
page := large[20:30]
fmt.Println(page) // 第3页(每页10条)
// 5. cmp.Or 链式回退
name := cmp.Or("", "Guest") // "Guest"
fmt.Println(name)
}标准库泛型清单
| 包 | 主要函数 | Go 版本 |
|---|---|---|
slices | Sort, Index, Contains, Insert, Delete, Clone, Equal, Compact | 1.21 |
maps | Clone, Copy, DeleteFunc, Equal | 1.21 |
cmp | Compare, Less, Or | 1.21 |
sort | 泛型 API 增强 | 1.22 |
要点总结
slices包是操作切片的瑞士军刀,覆盖查找、排序、修改、比较maps包让 map 操作更函数式(Clone、Copy、DeleteFunc)cmp.Compare是自定义排序的基础 — 几乎所有 SortFunc 都需要它cmp.Or是 Go 1.22 新增的实用函数,适合链式回退- 标准库泛型函数比自己写更优 — 经过严格测试、有优化