interface{}存在的问题

  1. 没有类型约束,可以传入任意值
  2. 类型断言相较于泛型性能较差
  3. 编写代码比较麻烦

基本概念

泛型 - 图1

基本使用

泛型参数

  1. type Slice[T int|float32|float64 ] []T
  2. var a Slice[int] = []int{1, 2, 3}
  3. type MyType[T int|float32|float64] T // 错误用法,不支持支持使用基础类型的泛型
  4. //正确的用法
  5. type Number interface {
  6. int|float32|float64
  7. }

泛型类型在使用前需要实例化,即指定具体类型

泛型Struct

  1. // 一个泛型类型的结构体。可用 int 或 sring 类型实例化
  2. type MyStruct[T int | string] struct {
  3. Name string
  4. Data T
  5. }
  6. a := MyStruct[int]{
  7. Name: "",
  8. Data: 123456789,
  9. }

泛型函数

  1. func Add[T int | float64 | float32](a, b T) T {
  2. return a + b
  3. }
  4. Add(10, 20)
  5. Add(1.01, 20) \\ 错误,此处编译器无法推断出类型,因此需要手动指定
  6. Add[float32](1.01, 20)

泛型方法

  1. type A[T int | float32 | float64] struct {
  2. }
  3. // 方法可以使用类型定义中的形参 T
  4. func (receiver A[T]) Add(a T, b T) T {
  5. return a + b
  6. }
  7. a := A[int]{}
  8. a.Add(12, 20)

注意:不支持如下方法

  1. type A struct {
  2. }
  3. // 方法可以使用类型定义中的形参 T
  4. func (receiver A) Add[T int | float64 | float32](a T, b T) T {
  5. return a + b
  6. }
  7. Method cannot have type parameters

泛型接口

接口定义自1.18后发生变化:
之前:

An interface type specifies a method set called its interface

最新:

An interface type defines a type set

接口的定义就从 方法集(method set) 变为了 类型集(type set)

any和comparable

自从1.18后,可使用any代替interface{}, 同时新增类型comparable(可比较类型),代表支持 == 和 != 操作符的类型。

  1. type MySlice [T any] T[]

类型的交集与并集

并集
可使用interface简化泛型集合

  1. type Int interface {
  2. ~int | ~int8 | ~int16 | ~int32 | ~int64
  3. }
  4. type MySlice[T Int] []T

但上面的写法存在一些问题:

  1. type MyInt int
  2. var a MySlice[MyInt] // 错误,虽然MyInt的底层类型为int,但并不在泛型集合中

为了解决上面的问题,可使用如下方式

  1. type _ interface {
  2. ~[]byte // 正确
  3. ~MyInt // 错误,~后的类型必须为基本类型
  4. ~error // 错误,~后的类型不能为接口
  5. }

~用于指定底层类型,~的使用条件:

  1. ~后面的类型不能为接口
  2. ~后面的类型必须为基本类型

交集

  1. type AllInt interface {
  2. ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint32
  3. }
  4. type Uint interface {
  5. ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
  6. }
  7. type A interface { // 接口A代表的类型集是 AllInt 和 Uint 的交集
  8. AllInt
  9. Uint
  10. }

空集

  1. type Bad interface {
  2. int
  3. float32
  4. }

这种写法表示取int和float32的交集,但是int和float没有交集,因此Bad表示空集,不代表任何类型

参考

Go 1.18 泛型全面讲解:一篇讲清泛型的全部