我想编写一个通用的 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
约束并将其转换为可以使用 ==
的内容。
有没有办法找出泛型类型 T any
在运行时是否是 comparable
,如果是,则使用 ==
进行比较?
我可以限制我的整个代码仅适用于 comparable
泛型类型,但我想让用户可以手动添加 equals
方法,如果他们的类型恰好不是 comparable
(例如,因为它基于切片) )。
正确答案
如果它使用相等运算符进行编译,则它是可比较的。受 any
约束的类型参数在定义上是不可比较的:它实际上可以是任何内容,包括 func() error
。
因此不可能使用静态类型编写 equals
函数。您必须使用反射或仅接受实现“相等”接口的参数,例如您自己的 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")
}
在这种情况下,使用泛型可能有助于在编译时确保 a
和 b
具有相同的确切类型,因此 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)
}
以上就是如何确定泛型类型在运行时是否“可比较”?的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1142
183.71 KB下载数642
644.84 KB下载数2755