我需要一个链接节点来保存一些不同的接口类型,所以我用泛型来制作它,但是泛型类型any
不能与 nil 进行比较,它显示错误,如注释中所示:
package main
type myInterface interface {
}
type node[T any] struct {
next *node[T]
leaf T
}
func (n *node[T]) GetFirstNodeHasLeaf() *node[T] {
if n.leaf != nil { // <---- error here: cannot compare n.leaf != nil (mismatched types T and untyped nil)
return n
}
if n.next == nil {
return nil
} else {
return n.next.GetFirstNodeHasLeaf()
}
}
func main() {
var n = &node[myInterface]{}
// fill n with lots of nodes
n.GetFirstNodeHasLeaf() // get the first node that has (leaf != nil)
}
Run Code Online (Sandbox Code Playgroud)
我还尝试与默认值进行比较
var nilT T
if n.leaf != nilT { // <-- same problem
Run Code Online (Sandbox Code Playgroud)
并将节点类型限制为
type node[T myInterface] struct {
Run Code Online (Sandbox Code Playgroud)
同样的错误,请问如何解决?谢谢。
bla*_*een 10
使用接口来实例化泛型类型node
可能是一个概念缺陷。因此,让我们先看一般情况,最后看接口情况。
comparable
和T
如果要对类型参数 type 的值使用等号运算符(例如==
和!=
),则约束必须是comparable
。
type node[T comparable] struct {
next *node[T]
leaf T
}
Run Code Online (Sandbox Code Playgroud)
但是,您不会针对 进行测试nil
,而是针对 的零值进行测试T
,根据您实例化它的内容,该零值可能是除 之外的其他值nil
。
T
在这种情况下,您可以为其零值声明一个类型变量:
var zero T
if n.leaf != zero {
return n
}
Run Code Online (Sandbox Code Playgroud)
但是接口类型不实现comparable
.
any
和*T
作为替代方案,您可以保留约束any
并将该字段声明leaf
为指向 的指针T
。它支持相等运算符,因为leaf
类型不再是类型参数,而是指针:
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
}
...
}
Run Code Online (Sandbox Code Playgroud)
any
和T
带约束any
,T
不支持等式运算符;您可以node
使用任何类型进行实例化,包括那些不可比较的类型。
只要该字段不是指针,您就只能使用反射来检查零值(nil
对于指针类型):
if !reflect.ValueOf(n.leaf).IsZero() {
return n
}
Run Code Online (Sandbox Code Playgroud)
T
最后,请考虑如果是接口类型,则上述代码不起作用。测试的是界面中装箱的动态值。如果T
确实必须是一个接口,请使用以下命令测试零值:
// leaf is an interface type
if !reflect.ValueOf(&n.leaf).Elem().IsZero() {
return n
}
Run Code Online (Sandbox Code Playgroud)