Skip to content

泛型入门

什么是泛型?

泛型允许你编写可以处理多种类型的函数或类型,而不需要为每种类型单独编写代码。通过泛型,调用代码可以提供具体的类型参数。

为什么需要泛型?

假设我们要计算map中所有值的总和,传统方式需要为不同类型写不同的函数:

go
// 处理int64类型的map
func SumInts(m map[string]int64) int64 {
    var s int64
    for _, v := range m {
        s += v
    }
    return s
}

// 处理float64类型的map
func SumFloats(m map[string]float64) float64 {
    var s float64
    for _, v := range m {
        s += v
    }
    return s
}

这样会产生重复代码,维护困难。

使用泛型解决问题

1. 基本泛型函数

go
// 使用泛型,一个函数处理多种类型
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V {
    var s V
    for _, v := range m {
        s += v
    }
    return s
}

关键概念:

  • [K comparable, V int64 | float64]类型参数
  • K comparable 表示K必须是可比较的类型(可以用作map的key)
  • V int64 | float64 表示V只能是int64或float64类型
  • | 表示类型联合(union)

2. 调用泛型函数

go
func main() {
    ints := map[string]int64{"first": 34, "second": 12}
    floats := map[string]float64{"first": 35.98, "second": 26.99}
    
    // 显式指定类型参数
    fmt.Printf("Generic Sums: %v and %v\n",
        SumIntsOrFloats[string, int64](ints),
        SumIntsOrFloats[string, float64](floats))
    
    // 类型推断(推荐)- 编译器自动推断类型
    fmt.Printf("Generic Sums: %v and %v\n",
        SumIntsOrFloats(ints),
        SumIntsOrFloats(floats))
}

3. 定义类型约束

为了重用和简化,可以将类型约束定义为接口:

go
// 定义类型约束接口
type Number interface {
    int64 | float64
}

// 使用自定义约束
func SumNumbers[K comparable, V Number](m map[K]V) V {
    var s V
    for _, v := range m {
        s += v
    }
    return s
}

完整示例

go
package main

import "fmt"

type Number interface {
    int64 | float64
}

func main() {
    ints := map[string]int64{"first": 34, "second": 12}
    floats := map[string]float64{"first": 35.98, "second": 26.99}

    fmt.Printf("Generic Sums: %v and %v\n",
        SumNumbers(ints),
        SumNumbers(floats))
}

func SumNumbers[K comparable, V Number](m map[K]V) V {
    var s V
    for _, v := range m {
        s += v
    }
    return s
}

核心要点

  1. 类型参数:在函数名后用方括号 [] 声明
  2. 类型约束:限制类型参数可以使用的具体类型
  3. 类型推断:Go编译器通常可以自动推断类型,无需显式指定
  4. 类型联合:使用 | 连接多个允许的类型
  5. comparable:内置约束,表示可比较的类型(可用作map的key或进行 == 比较)

使用场景

  • 需要处理多种相似类型的通用算法
  • 避免为不同类型编写重复代码
  • 提高代码复用性和类型安全性

泛型让Go代码更加灵活和可重用,同时保持类型安全!

Released under the MIT License.