interface{}存在的问题
- 没有类型约束,可以传入任意值
- 类型断言相较于泛型性能较差
- 编写代码比较麻烦
基本概念
基本使用
泛型参数
type Slice[T int|float32|float64 ] []T
var a Slice[int] = []int{1, 2, 3}
type MyType[T int|float32|float64] T // 错误用法,不支持支持使用基础类型的泛型
//正确的用法
type Number interface {
int|float32|float64
}
泛型类型在使用前需要实例化,即指定具体类型
泛型Struct
// 一个泛型类型的结构体。可用 int 或 sring 类型实例化
type MyStruct[T int | string] struct {
Name string
Data T
}
a := MyStruct[int]{
Name: "",
Data: 123456789,
}
泛型函数
func Add[T int | float64 | float32](a, b T) T {
return a + b
}
Add(10, 20)
Add(1.01, 20) \\ 错误,此处编译器无法推断出类型,因此需要手动指定
Add[float32](1.01, 20)
泛型方法
type A[T int | float32 | float64] struct {
}
// 方法可以使用类型定义中的形参 T
func (receiver A[T]) Add(a T, b T) T {
return a + b
}
a := A[int]{}
a.Add(12, 20)
注意:不支持如下方法
type A struct {
}
// 方法可以使用类型定义中的形参 T
func (receiver A) Add[T int | float64 | float32](a T, b T) T {
return a + b
}
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(可比较类型),代表支持 == 和 != 操作符的类型。
type MySlice [T any] T[]
类型的交集与并集
并集
可使用interface简化泛型集合
type Int interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}
type MySlice[T Int] []T
但上面的写法存在一些问题:
type MyInt int
var a MySlice[MyInt] // 错误,虽然MyInt的底层类型为int,但并不在泛型集合中
为了解决上面的问题,可使用如下方式
type _ interface {
~[]byte // 正确
~MyInt // 错误,~后的类型必须为基本类型
~error // 错误,~后的类型不能为接口
}
~用于指定底层类型,~的使用条件:
- ~后面的类型不能为接口
- ~后面的类型必须为基本类型
交集
type AllInt interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint32
}
type Uint interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
type A interface { // 接口A代表的类型集是 AllInt 和 Uint 的交集
AllInt
Uint
}
空集
type Bad interface {
int
float32
}
这种写法表示取int和float32的交集,但是int和float没有交集,因此Bad表示空集,不代表任何类型