Skip to content

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], // 自定义值的比较函数
)  // true

cmp 包 — 比较函数 ​

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 版本
slicesSort, Index, Contains, Insert, Delete, Clone, Equal, Compact1.21
mapsClone, Copy, DeleteFunc, Equal1.21
cmpCompare, Less, Or1.21
sort泛型 API 增强1.22

要点总结 ​

  1. slices 包是操作切片的瑞士军刀,覆盖查找、排序、修改、比较
  2. maps 包让 map 操作更函数式(Clone、Copy、DeleteFunc)
  3. cmp.Compare 是自定义排序的基础 — 几乎所有 SortFunc 都需要它
  4. cmp.Or 是 Go 1.22 新增的实用函数,适合链式回退
  5. 标准库泛型函数比自己写更优 — 经过严格测试、有优化