如何为两个原始类型和定义类型定义类型约束?
我有一个用例,我希望能够比较两个值并查看一个更大的值,但是我也希望能够通过实现接口来参与复合类型。
类似的东西
type Ordered interface {
~int | ~float32 | ~string // ...
}
type OrderedValue[T Ordered] interface {
Value() T
}
我希望我的比较函数能够接受两个有序的参数并返回结果,或两个orderedValues
并调用value()
进行比较的方法。 类似:
func doCompare[T Ordered](a, b T) int {
if a > b {
return 1
} else if a < b {
return -1
}
return 0
}
func Compare[U Ordered, V OrderedValue[U], T U | V](a, b T) int {
var i interface{} = a
if _, ok := i.(OrderedValue[U]); ok {
return doCompare(a.Value(), b.Value())
}
return doCompare(a, b)
}
对于比较函数,我会收到错误消息
不能嵌入类型参数
,并且在接口情况下调用DOCOMPARE时,我会得到
a.Value undewined(T型没有字段或方法值)
b.Value不确定(T型没有字段或方法值)
我在这里看到了一个问题,暗示这可能是不可能的,但是这个问题如何迭代以通用功能通过的切片结合? (t没有核心类型)让我希望有一种聪明的方法,我只是没有看到。
我希望避免为内置类型定义框实现以支持这一点。任何指导将不胜感激。
这是一个Go Playground 它具有更完整的示例
I have a use case where I'd like to be able to compare two values and see which one is larger, but I'd also like to be able for composite types to participate by implementing an interface.
Something like
type Ordered interface {
~int | ~float32 | ~string // ...
}
type OrderedValue[T Ordered] interface {
Value() T
}
Then I'd like my Compare function to be able accept either two ordered arguments and return the result, or two OrderedValues
and call the Value()
method to do compare.
Something like:
func doCompare[T Ordered](a, b T) int {
if a > b {
return 1
} else if a < b {
return -1
}
return 0
}
func Compare[U Ordered, V OrderedValue[U], T U | V](a, b T) int {
var i interface{} = a
if _, ok := i.(OrderedValue[U]); ok {
return doCompare(a.Value(), b.Value())
}
return doCompare(a, b)
}
For the Compare function I get error message
cannot embed a type parameter
And when calling doCompare in the interface case I get
a.Value undefined (type T has no field or method Value)
b.Value undefined (type T has no field or method Value)
I have seen one question here that implies this may not be possible, but this one How to iterate over a union of slices passed in a generic function? (T has no core type) gave me hope that there may be a clever way of doing this that I'm just not seeing.
I was hoping to avoid having to define Box implementations for built-in types to support this. Any guidance would be appreciated.
Here is a go playground that has more complete example
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你不能(很棒)。
您想要的约束可以总结为“有序的原始方法或提供有序原始的方法”。这不能用GO 1.18表示,因为
,可以烹饪一些编译的东西,但是它会非常怪异,它不会利用类型推理。
我相信目前最干净的解决方案只是原始类型和定义类型的两个不同的功能:
如果未来释放放宽了非基础接口和约束的限制,例如允许非基础接口,例如
constraints.ordered.sorderseds. /code>在类型开关中,或允许工会中仅使用方法的接口,那么这可能具有更好的解决方案。
从GO 1.18开始,您应该坚持使用类型参数的行为完全相同的事物。
You can't (sanely).
The constraint you want can be summarized as "ordered primitive or method that gives an ordered primitive". This can't be expressed with Go 1.18 because
It's possible to cook out something that compiles, but it would be very weird, and it wouldn't take advantage of type inference.
I believe the cleanest solution at this time is just two different functions for primitives and defined types:
If future Go releases relax the limitations on non-basic interfaces and constraints, such as allowing non-basic interfaces such as
constraints.Ordered
in type switches, or allowing method-only interfaces in unions, then this might have nicer solutions.As of Go 1.18, you should stick to using type parameters for things that behave exactly the same.