泛型
# 概述
如果我们想实现一个简单的tree数据结构,每个节点持有一个值。在Go 1.18之前,实现这种结构的典型方法如下:
type Node struct{
value interface{}
}
1
2
3
2
3
这在大多少情况下,都很好用,但他也有一些缺点。 首先,interface{} 可以是任何东西,如果我们想限制value可能持有的类型,例如整数和浮点数,我们只能在运行时检查这个限制。
func (n Node) IsValid() bool {
switch n.value.(type) {
case int, float32, float64:
return true
default:
return false
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
这样并不可能在编译时限制类型,像上面这样的类型判断在许多Go库中都是很常见的做法。 第二,对Node中的值进行处理是非常繁琐和容易出错的。对值做任何事情都会涉及到某种类型的断言,即使你可以安全的假设值持有一个int值。
num, ok := node.value.(int)
if !ok {
}
double := number * 2
1
2
3
4
5
2
3
4
5
这些只是使用interface{}的一些不便之处,它既没有提供类型安全,并有可能导致难以恢复的运行时错误。
# 解决方法
我们不打算接受任意数据类型或数据类型,而是定义一个叫做T的占位符类型,作为值的类型。请注意,这段代码还不会通过编译。
type Node(T) struct {
value T
}
1
2
3
2
3
首先需要声明泛型类型T,这是在结构或函数名称后面方括号里使用的。T 可以是任何类型,只有实例化一个具有明确类型的Node时,T才会被推导为该类型。
n := Node[int] {
value: 5,
}
1
2
3
2
3
泛型Node被实例化为Nodeint,所以T是一个int。
类型约束 上面的实现里,
上次更新: 2023/01/11