基本概念
类型形参、类型实参、类型约束和泛型类型
type Slice[T int|float32|float64 ] []T
类型形参 T。类型占位符,不表示具体的类型
类型约束 int|float32|float64。 中间的 | 的意思是告诉编译器,类型形参 T 只可以接收 int 或 float32 或 float64 这三种类型的实参
类型参数列表 T int|float32|float64
泛型类型 type Slice[T int|float32|float64 ] []T。完整的泛型类型定义
泛型类型实例化
// 这里传入了类型实参int,泛型类型Slice[T]被实例化为具体的类型 Slice[int]
var a Slice[int] = []int{1, 2, 3} 
类型实参 Slice[int] 中的 int
泛型Receiver
func (s Slice[T]) Sum() T {
    var sum T
    for _, value := range s {
        sum += value
    }
    return sum
}
var s Slice[int] = []int{1, 2, 3, 4}
fmt.Println(s.Sum()) // 输出:10
var s2 Slice[float32] = []float32{1.0, 2.0, 3.0, 4.0}
fmt.Println(s2.Sum()) // 输出:10.0
泛型函数
func Add(a int, b int) int {
    return a + b
}
func Add[T int|float32|float64](a T, b T) T {
    return a + b
}
Add[int](1,2) // 传入类型实参int,计算结果为 3
Add[float32](1.0, 2.0) // 传入类型实参float32, 计算结果为 3.0
Add[string]("hello", "world") // 错误。因为泛型函数Add的类型约束中并不包含string
Go标准库提供的泛型库
slices,maps 库
var list []int{3, 2, 1}
slices.Sort(list) //排序
slices.Reverse(list) //翻转
slices.Contains(list, 1) //是否包含
...
m := map[string]int{
  "a": 1,
  "b": 2,
  "c": 3,
}
maps.Keys(m) //提取 key ["a", "b", "c"]
maps.Values(m) //提取 value [1, 2, 3]
maps.Clone(m) //克隆
...
总结
当你需要针对不同类型书写同样的逻辑,使用泛型来简化代码是最好的 (比如写个队列,写个链表、栈、堆之类的数据结构)
https://segmentfault.com/a/1190000041634906#item-2