Go 泛型
基础
泛型函数
目前不支持泛型方法,需要依赖于泛型 receiver
泛型类型
基础使用
泛型结构体
泛型接口
泛型通道
泛型类型的套娃
类型形参的相互调用
一般不会这么写
可能更好的写法
泛型 receiver
可以像给普通结构体一样,给泛型结构体添加方法
没有泛型前想实现通用的数据结构,例如:堆、栈、队列等,只有两个选择:
1、为每种类型写一个实现
2、使用接口 + 反射
1、为每种类型写一个实现
2、使用接口 + 反射
基于泛型的队列
动态判断变量的类型
使用接口时经常使用 类型断言 或 type switch 来确定接口的类型,然后对不同类型做不同处理
对于 value T 这样的泛型类型,无法使用上面的操作
但是可以通过反射获取到 value 的 Kind 再去判断,从而达到目的
但是可以通过反射获取到 value 的 Kind 再去判断,从而达到目的
思考:你为了避免使用反射而选择了泛型,结果又为了一些功能在泛型中使用反射,是否值得?
注意事项
定义泛型类型的时候,基础类型不能只有类型形参
当类型约束的一些写法会被编译器误认为是表达式时会报错(例如 指针类型)
可以使用 interface{} 消除歧义
可以使用 interface{} 消除歧义
匿名结构体不支持泛型
匿名函数不支持泛型
目前(截至 Go 1.20)支持泛型函数,但是不支持泛型方法
小结
Go 的泛型目前的使用场景
1. 泛型类型
结构体
管道
接口
2. 泛型 receiver
3. 泛型函数
Go 泛型中的一些概念
类型形参
类型形参列表
类型实参
类型约束
实例化
进阶
使用 | 组合接口
使用 ~ 指定底层类型
~ 后面的类型必须是基本类型,不能为接口
方法集到类型集
基本接口:接口中只有方法
常用用法,定义接口变量并赋值
基本接口因为也代表了一个类型集,所以也可用在类型约束中
一般接口:接口中不光有方法,还有类型
一般接口不能用来定义变量,只能用于泛型的约束中
这个限制保证了一般接口的使用被限定在泛型中,并且不会影响到 Go 1.18 以前的代码
这个限制保证了一般接口的使用被限定在泛型中,并且不会影响到 Go 1.18 以前的代码
接口定义的限制
用 | 连接多个类型的时候,类型之间不能有相交的部分(即必须是不交集)
但是相交的类型中是接口的话,则不受这一限制
类型的并集中不能有类型形参
接口不能直接或间接地并入自己
接口的并集成员个数大于一的时候不能直接或间接并入 comparable 接口
带方法的接口(无论是基本接口还是一般接口),都不能写入接口的并集中
总结
泛型的使用场景
泛型并不取代 Go1.18 之前用接口 + 反射实现的动态类型
当你需要针对不同类型书写同样的逻辑,使用泛型来简化代码是最好的
(比如你想写个队列,写个链表、栈、堆之类的数据结构)
(比如你想写个队列,写个链表、栈、堆之类的数据结构)