Go 泛型

2 minAdvanced2026/6/14

Go 1.18+ 泛型、类型参数、约束、泛型函数与类型、类型推断、slices/maps/cmp 标准库包与泛型实际应用。

1. 泛型概述

Go 1.18(2022.03)正式引入泛型,是 Go 语言最重要的特性之一。泛型允许编写与型无关的代码,同时保持型安全。

1.1 为什么需要泛型

// 没有泛型时:每种类型写一个函数
func MaxInt(a, b int) int {
    if a > b { return a }
    return b
}

func MaxFloat64(a, b float64) float64 {
    if a > b { return a }
    return b
}

func MaxString(a, b string) string {
    if a > b { return a }
    return b
}

// 或者使用 any(丢失类型安全)
func MaxAny(a, b any) any {
    // 需要类型断言,运行时才能发现错误
}

1.2 泛型版本

func Max[T cmp.Ordered](a, b T) T {
    if a > b { return a }
    return b
}

fmt.Println(Max(3, 5))           // 5
fmt.Println(Max(3.14, 2.71))     // 3.14
fmt.Println(Max("abc", "xyz"))   // xyz

2. 型参数

2.1 语法

// 函数泛型
func FuncName[T constraint](params T) T { ... }

// 多类型参数
func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 { ... }

// 类型泛型
type Container[T any] struct {
    data T
}

2.2 型参数列表

// 单类型参数
func Print[T any](v T) {
    fmt.Println(v)
}

// 多类型参数
func Pair[T1, T2 any](a T1, b T2) struct{ F1 T1; F2 T2 } {
    return struct{ F1 T1; F2 T2 }{a, b}
}

// 类型参数可以互相引用
func Convert[T1, T2 any](s []T1, f func(T1) T2) []T2 {
    result := make([]T2, len(s))
    for i, v := range s {
        result[i] = f(v)
    }
    return result
}

3. 约束(Constraint)

约束定义了型参数必须满足的条件,本质上是接口

3.1 any 约束

// any 是 interface{} 的别名,最宽松的约束
func Print[T any](v T) {
    fmt.Println(v)
}

3.2 comparable 约束

// comparable 允许 == 和 != 操作
func Contains[T comparable](s []T, v T) bool {
    for _, item := range s {
        if item == v {
            return true
        }
    }
    return false
}

fmt.Println(Contains([]string{"a", "b", "c"}, "b")) // true
fmt.Println(Contains([]int{1, 2, 3}, 4))             // false

3.3 cmp.Ordered 约束

import "cmp"

// cmp.Ordered 包含所有支持 < > <= >= 的类型
// ~int | ~int8 | ~int16 | ~int32 | ~int64 |
// ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
// ~float32 | ~float64 | ~string

func Max[T cmp.Ordered](a, b T) T {
    if a > b { return a }
    return b
}

func Sort[T cmp.Ordered](s []T) {
    slices.Sort(s)
}

3.4 自定义约束

// 方法约束
type Stringer interface {
    String() string
}

func Join[T Stringer](items []T, sep string) string {
    strs := make([]string, len(items))
    for i, item := range items {
        strs[i] = item.String()
    }
    return strings.Join(strs, sep)
}

// 联合类型约束(使用 | )
type Number interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64 |
    ~float32 | ~float64
}

func Sum[T Number](nums []T) T {
    var total T
    for _, n := range nums {
        total += n
    }
    return total
}

// ~ 表示底层类型(underlying type)
type MyInt int // MyInt 的底层类型是 int

// ~int 匹配 int 和所有底层类型为 int 的自定义类型
// int 只匹配 int 本身

3.5 约束中的型成员

// 约束可以包含类型
type Number interface {
    ~int | ~float64
}

// 复杂约束示例
type SliceConstraint[S any] interface {
    ~[]S
}

func Last[S any, T SliceConstraint[S]](s T) S {
    return s[len(s)-1]
}

4. 泛型函数

4.1 常用泛型函数

// Map — 转换切片元素
func Map[T, U any](s []T, f func(T) U) []U {
    result := make([]U, len(s))
    for i, v := range s {
        result[i] = f(v)
    }
    return result
}

doubled := Map([]int{1, 2, 3}, func(n int) int { return n * 2 })
// [2, 4, 6]

// Filter — 过滤切片
func Filter[T any](s []T, pred func(T) bool) []T {
    var result []T
    for _, v := range s {
        if pred(v) {
            result = append(result, v)
        }
    }
    return result
}

evens := Filter([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 })
// [2, 4]

// Reduce — 归约
func Reduce[T, U any](s []T, init U, f func(U, T) U) U {
    acc := init
    for _, v := range s {
        acc = f(acc, v)
    }
    return acc
}

sum := Reduce([]int{1, 2, 3}, 0, func(acc, n int) int { return acc + n })
// 6

4.2 泛型接口结合

type Adder[T any] interface {
    Add(T) T
}

func SumAll[T Adder[T]](items []T) T {
    if len(items) == 0 {
        var zero T
        return zero
    }
    result := items[0]
    for _, item := range items[1:] {
        result = result.Add(item)
    }
    return result
}

5. 泛型

5.1 泛型结构体

type Pair[T, U any] struct {
    First  T
    Second U
}

func NewPair[T, U any](first T, second U) Pair[T, U] {
    return Pair[T, U]{First: first, Second: second}
}

p := NewPair("name", 42)
fmt.Println(p.First, p.Second) // name 42

5.2 泛型

type Stack[T any] struct {
    items []T
}

func (s *Stack[T]) Push(v T) {
    s.items = append(s.items, v)
}

func (s *Stack[T]) Pop() (T, bool) {
    if len(s.items) == 0 {
        var zero T
        return zero, false
    }
    top := s.items[len(s.items)-1]
    s.items = s.items[:len(s.items)-1]
    return top, true
}

func (s *Stack[T]) Peek() (T, bool) {
    if len(s.items) == 0 {
        var zero T
        return zero, false
    }
    return s.items[len(s.items)-1], true
}

func (s *Stack[T]) Len() int {
    return len(s.items)
}

// 使用
stack := Stack[int]{}
stack.Push(1)
stack.Push(2)
v, _ := stack.Pop() // 2

5.3 泛型 map

type Map[K comparable, V any] struct {
    data map[K]V
}

func NewMap[K comparable, V any]() *Map[K, V] {
    return &Map[K, V]{data: make(map[K]V)}
}

func (m *Map[K, V]) Get(key K) (V, bool) {
    v, ok := m.data[key]
    return v, ok
}

func (m *Map[K, V]) Set(key K, value V) {
    m.data[key] = value
}

func (m *Map[K, V]) Delete(key K) {
    delete(m.data, key)
}

func (m *Map[K, V]) Keys() []K {
    keys := make([]K, 0, len(m.data))
    for k := range m.data {
        keys = append(keys, k)
    }
    return keys
}

5.4 泛型接口

type Container[T any] interface {
    Add(T)
    Get() (T, bool)
    Size() int
}

type List[T any] []T

func (l *List[T]) Add(v T)      { *l = append(*l, v) }
func (l *List[T]) Get() (T, bool) {
    if len(*l) == 0 {
        var zero T
        return zero, false
    }
    return (*l)[0], true
}
func (l *List[T]) Size() int    { return len(*l) }

var c Container[int] = &List[int]{}

6. 型推断

Go 编译器可以自动推断大部分型参数,无需显式指定:

func Map[T, U any](s []T, f func(T) U) []U

// 完整指定
result := Map[int, string]([]int{1, 2, 3}, func(n int) string {
    return strconv.Itoa(n)
})

// 类型推断(推荐)
result := Map([]int{1, 2, 3}, func(n int) string {
    return strconv.Itoa(n)
})

// 部分推断失败时需显式指定
// 例如:约束不够明确时

7. 标准库泛型

7.1 slices 包

import "slices"

nums := []int{3, 1, 4, 1, 5, 9}

// 排序
slices.Sort(nums)                       // [1 1 3 4 5 9]

// 搜索
idx := slices.Index(nums, 4)            // 3

// 包含
slices.Contains(nums, 5)                // true

// 二分查找(需先排序)
slices.BinarySearch(nums, 4)            // 3, true

// 比较
slices.Equal([]int{1, 2}, []int{1, 2})  // true

// 自定义比较排序
type Person struct {
    Name string
    Age  int
}
people := []Person{{"Alice", 30}, {"Bob", 25}}
slices.SortFunc(people, func(a, b Person) int {
    return cmp.Compare(a.Age, b.Age)
})

// 插入/删除
slices.Insert(nums, 2, 99)              // 在索引 2 插入
slices.Delete(nums, 1, 3)               // 删除 [1, 3) 范围

// 克隆
clone := slices.Clone(nums)

// 反转
slices.Reverse(nums)

// 去重(排序后)
slices.Sort(nums)
nums = slices.Compact(nums)

7.2 maps 包

import "maps"

m := map[string]int{"a": 1, "b": 2, "c": 3}

// 获取所有键
keys := maps.Keys(m)     // []string{"a", "b", "c"}(顺序不确定)

// 获取所有值
vals := maps.Values(m)   // []int{1, 2, 3}

// 克隆
clone := maps.Clone(m)

// 复制
dst := map[string]int{}
maps.Copy(dst, m)

// 删除满足条件的元素
maps.DeleteFunc(m, func(k string, v int) bool {
    return v < 2
})
// m = {"b": 2, "c": 3}

// 相等比较
maps.Equal(map[string]int{"a": 1}, map[string]int{"a": 1}) // true

7.3 cmp 包

import "cmp"

// 比较有序类型
cmp.Compare(3, 5)     // -1(a < b)
cmp.Compare(5, 3)     // 1 (a > b)
cmp.Compare(3, 3)     // 0 (a == b)
cmp.Compare("abc", "xyz") // -1

// 比较有序类型(返回布尔)
cmp.Less(3, 5)        // true
cmp.Less("b", "a")    // false

// Ordered 约束
func Min[T cmp.Ordered](a, b T) T {
    if cmp.Less(a, b) {
        return a
    }
    return b
}

8. 泛型实际应用

8.1 泛型缓存

type Cache[K comparable, V any] struct {
    data map[K]V
    mu   sync.RWMutex
}

func NewCache[K comparable, V any]() *Cache[K, V] {
    return &Cache[K, V]{data: make(map[K]V)}
}

func (c *Cache[K, V]) Get(key K) (V, bool) {
    c.mu.RLock()
    defer c.mu.RUnlock()
    v, ok := c.data[key]
    return v, ok
}

func (c *Cache[K, V]) Set(key K, value V) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.data[key] = value
}

// 使用
userCache := NewCache[string, *User]()
userCache.Set("alice", &User{Name: "Alice"})
user, ok := userCache.Get("alice")

8.2 泛型结果

type Result[T any] struct {
    Value T
    Err   error
}

func Ok[T any](v T) Result[T] {
    return Result[T]{Value: v}
}

func Err[T any](err error) Result[T] {
    return Result[T]{Err: err}
}

func (r Result[T]) IsOk() bool    { return r.Err == nil }
func (r Result[T]) IsErr() bool   { return r.Err != nil }
func (r Result[T]) Unwrap() T {
    if r.Err != nil {
        panic(r.Err)
    }
    return r.Value
}

func (r Result[T]) UnwrapOr(defaultVal T) T {
    if r.Err != nil {
        return defaultVal
    }
    return r.Value
}

// 使用
func fetchData(url string) Result[string] {
    resp, err := http.Get(url)
    if err != nil {
        return Err[string](err)
    }
    defer resp.Body.Close()
    data, err := io.ReadAll(resp.Body)
    if err != nil {
        return Err[string](err)
    }
    return Ok(string(data))
}

result := fetchData("https://api.example.com")
if result.IsOk() {
    fmt.Println(result.Value)
}

8.3 泛型注意事项

// 1. 不支持方法泛型
type Container[T any] struct{ data T }
// func (c Container[T]) Do[S any](v S) {} // 编译错误

// 解决方案:使用泛型函数
func Do[T, S any](c Container[T], v S) {}

// 2. 不支持泛型断言
// var x any = 42
// _ = x.(T) // 编译错误

// 3. 零值获取
func Zero[T any]() T {
    var zero T
    return zero
}

// 4. Go 1.24+ 泛型类型别名
type Set[T comparable] = map[T]struct{}
type OrderedMap[K comparable, V cmp.Ordered] = map[K]V