使用接口实例化泛型类型,例如node
可能是一个概念缺陷。因此,让我们先看一般情况,最后看接口情况。
Using comparable
and T
如果你想使用等号运算符==
and !=
对于类型参数类型的值,约束必须是comparable
.
type node[T comparable] struct {
next *node[T]
leaf T
}
但你不会去测试nil
,你会测试T
的零值,根据您实例化它的内容,它可能不是nil
.
在这种情况下,您将声明一个类型的变量T
其零值:
var zero T
if n.leaf != zero {
return n
}
但是接口类型不实现comparable
.
Using any
and *T
作为替代方案,您可以保留约束any
并声明该字段leaf
作为指向T
。这支持相等运算符,因为leaf
type 不再是类型参数,而是指针:
type node[T any] struct {
next *node[T]
leaf *T
}
func (n *node[T]) GetFirstNodeHasLeaf() *node[T] {
if n.leaf != nil { // ok, leaf is a pointer type
return n
}
...
}
Using any
and T
随着约束any
, T
不支持相等运算符;你可以实例化node
几乎任何类型,包括那些不可比较的类型。
只要该字段不是指针,就只能使用反射来检查零值(nil
对于指针类型`):
if !reflect.ValueOf(n.leaf).IsZero() {
return n
}
最后,考虑一下上面的代码在以下情况下不起作用:T
是一种接口类型。测试的是界面中装箱的动态值。如果T
确实必须是一个接口,用以下方法测试零值:
// leaf is an interface type
if !reflect.ValueOf(&n.leaf).Elem().IsZero() {
return n
}