我想编写一个通用的equals方法,其工作原理如下:

func equals[T any](a, b T) bool {
  if hasEqualsMethod(T) {
    return a.Equals(b)
  else if isComparable(T) {
    return a == b
  }
  panic("type cannot be compared")
} 

为此,我创建了一个接口Comparable:

type Comparable[T any] interface {
    // Equals returns true if the receiver and the argument are equal.
    Equals(T) bool
}

我可以判断equals的参数是否实现了这个Comparable接口,如下所示:

func equals[T any](a, b T) bool {
    aComp, ok := any(a).(Comparable[T])
    if ok {
        return aComp.Equals(b)
    }
    ...

然而,到目前为止,我还没有发现a是否也满足comparable约束并将其转换为可以使用==的东西的可能性.

Is there any way to find out if a generic type 100 is 101 during runtime and, if so, compare it using 102?

我可以将我的整个代码限制为只处理comparable个泛型类型,但我想让用户可以手动添加equals方法,如果他们的类型恰好不是comparable的话(例如,因为它是基于片的).

推荐答案

如果它使用相等运算符进行编译,则是可比较的.根据定义,受any约束的类型参数不具有可比性:它可以是任何东西,包括func() error.

因此,用静态类型编写equals函数是不可能的.您必须使用反射或只接受实现"EQUALER"接口的参数,如您自己的Comparable[T any].

使用反射,您可以使用Value#Comparable:

func equals[T any](a, b T) bool {
    v := reflect.ValueOf(a)
    if v.Comparable() {
        u := reflect.ValueOf(b)
        return v.Equal(u)
    }
    panic("type cannot be compared")
}

在这种情况下,泛型的使用可能有助于在编译时确保ab具有相同的类型,因此v.Equal(u)不是没有意义的,而不是声明equals(a, b any).

使用"Equaler"接口,您必须提供实现该接口的命名类型,以便转换预声明的类型并对其调用方法:

func main() {
    fmt.Println(equals(EqualerFloat64(5.57), EqualerFloat64(5.57)))
}

type Equaler[T any] interface {
    Equal(T) bool
}

type EqualerFloat64 float64

func (f EqualerFloat64) Equal(f2 EqualerFloat64) bool {
    return f == f2
}

func equals[T Equaler[T]](a, b T) bool {
    return a.Equal(b)
}

Go相关问答推荐

Go编译器标志-修剪路径不完全工作

难以为多个平台添加Go Bazel构建选项

链自定义GRPC客户端拦截器/DialOptions

将类型定义为泛型类型实例化

允许在 struct 中使用复合作为函数参数

使用Digitorus/pdfsign在GO(Golang)中签署pdf文件

无法使用Segentio;S Kafka-Go连接到融合的Kafka

如何使redis池的等待超时

Python样式生成器实现为通道:过早读取

不接受来自 stdin 的重复输入

正则表达式模式,确保至少一个字符与其他条件一起存在

创建新对象后如何返回嵌套实体?

如何在 Go 中编写示例测试?

在 Go 中公开公共 JWK

golang 中的可变参数函数

致命错误:找不到由 zergon321/reisen 引起的libavcodec/avcodec.h文件

从 os.stdout 读取

无法建立连接,因为目标机器主动拒绝它 Golang

Grafana/Prometheus 将多个 ip 可视化为查询

在 Go 中,为什么 exec.Command() 失败但 os.StartProcess() 成功启动winget.exe?