使用泛型:运算符==未为T定义

我在操场上玩 Go 泛型,试图编写一些通用数组函数。

https://go2goplay.golang.org/p/PFb1jhy1fML

package main

import (
    "fmt"
)

func array_has[T any](haystack []T, needle T) bool {
    for _, val := range haystack {
        if val == needle {
            return true
        }
    }
    return false
}


func main() {
    arr := []string{"A","B","C"}
    fmt.Println(array_has(arr, "T"))
}

我得到的错误是:

type checking failed for main
prog.go2:9:6: cannot compare val == needle (operator == not defined for T)

我可以通过使用反射来解决它:

if reflect.ValueOf(val).Interface() == reflect.ValueOf(needle).Interface()

Go2 游乐场:https ://go2goplay.golang.org/p/9ZVZafQ_9JK

但是,是否有一个(内部?)“可比较”类型的接口==,为此我可以使用它来代替any

真的有甚至不支持与 比较的类型==吗?

回答

比较运算符==!=只能用于确实可比较的参数化类型。

这些在Go 规范中明确定义:比较运算符。特别是:

切片、映射和函数值不可比较。

通过使用类型约束any,您实际上允许任何类型,包括切片、映射和函数。由于这些类型首先不可比较,因此 Go2 编译器会抱怨您提到的错误:

无法比较 val == 针(运算符 == 未为 T 定义)

当前的实现确实提供了一个预先声明的标识符 comparable,将类型参数限制为那些确实定义了==和 的!=

所以写函数签名的正确方法是

func array_has[T comparable](haystack []T, needle T) bool

为清楚起见,请注意这comparable预先声明的 identifier,而不是关键字。不同之处在于您可以在更窄的范围内重新声明它并隐藏内置的范围。需要明确的是,以下程序确实可以编译:

package main

func main() {
    comparable := 1
    fmt.Println(comparable)
}

我认为您通常不需要重新声明标识符,但很高兴知道,因为这是泛型实现向后兼容早期 Go 版本的原因之一,即具有名为“comparable”的变量的旧程序仍将编译.

请记住,comparable正在讨论标识符和类似的内置便利类型。假设这个提议不会改变太多是有点安全的,但是最终的类型参数实现可能会以一些额外的结构结束,用于限制可比较的类型,例如专用包中的导出接口constraints.Comparable。请务必在几个月后回来查看。


以上是使用泛型:运算符==未为T定义的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>