golang在1.18.x版本中,已经支持了泛型,从代码实现上看,整体在使用上比较简洁,但是如果结合面型对象思想做一些常见数据结构开发的时候,就会遇到各种各样的问题,该文将现以 队列 和 链表 两个数据结构还说明泛型的使用,相关代码我会放在github中。 github.com/xiezy1997/g...
如何在func中使用泛型?
- 原始的func书写形式
go
func Sum(a, b int) int {
return a + b
}
- 泛型的func书写形式
go
func Sum[T int64 | float64](a, b T) T {
return a + b
}
通过代码对比我们就可以看出,泛型是在funcName后面增加了一个[T],用来表示T的类型,那么我们在调用的时候,既可以显示告知方法类型,也可让方法自动识别类型是否匹配。
- 调用方法
go
fmt.Println(Sum[int64](a, b))
fmt.Println(Sum(c, d))
定义泛型的时候一定要枚举所有类型吗?
当然是不需要的啦,golang内置了一些约束,也可以自定义一些约束,以简化代码书写
- 内置约束
内置约束 | 注意事项 |
---|---|
any | 实则interface{} |
comparable | 必须支持"=="方法 |
- 自定义约束
go
type Int interface {
int | int8 | int16 | int32 | int64
}
func Sum[T Int](a, b T) T {
return a + b
}
如何在struct中使用泛型?
go
type LinkList[T any] struct {
head *node[T]
tail *node[T]
cnt int
}
type node[T any] struct {
data T
next *node[T]
}
其实我们将泛型应用在struct中也是十分简单的,只要我们在structName后面加上[T]即可在struct使用了,但是需要注意我们在创建这个struct对象的时候,需要显示指定这个T实际类型
n := &node[int]{}
如何在接口中使用泛型?
go
type IMath[T any] interface {
Sum(a, b T) T
}
在interface中,我们也是只需要在interfaceName后面加上[T]即可使用泛型了
如何在常见数据结构中使用泛型呢?
其实我们只需要将struct、interface、func以及泛型整合到一起,即可实现在数据结构中使用泛型,具体可以看 github.com/xiezy1997/g...,此处仅放一个方法作为demo
go
// interface.go
type ILinkList[T any] interface {
// Iterator 获取迭代器函数
// @param ctx
// @return func() (T, bool): data, isNull
Iterator(ctx context.Context) func() (T, bool)
}
// linklist.go
type LinkList[T any] struct {
head *node[T]
tail *node[T]
cnt int
}
func (l *LinkList[T]) Iterator(ctx context.Context) func() (T, bool) {
p := l.head // 此处使用闭包的特性,实现迭代器操作
return func() (T, bool) {
if p == nil {
var t T // 这里不能直接返回nil,一旦T不是指针的话,返回nil会出现panic,所以此处需要先创建其变量再返回
return t, true
}
data := p.data
p = p.next
return data, false
}
}
func NewLinkList[T any]() ILinkList[T] {
return &LinkList[T]{}
}
// types.go
type node[T any] struct {
data T
next *node[T]
}
func newNode[T any]() *node[T] {
return &node[T]{}
}