我想创建一个 Vector 类型,它在其内部数据上是通用的,但在给定输入类型的方法实现方式上可能有所不同。
type SupportedType interface {
~int64 | ~uint64 | ~float64 | string | bool | time.Time
}
type Vec[T SupportedType] struct {
data []T
}
我想根据类型在函数上添加不同的实现。例如:
func (vec Vec[T]) Sort() {
...
}
在大多数泛型类型中 <
会工作得很好。但是,如果 T -> time.Time
我想使用 Before
方法和如果 T --> bool
然后我希望所有错误值都在真实值之前。
我对如何实现这一点有一些想法,但在新的泛型世界中,什么会被认为是“惯用的”?我的应用程序对性能敏感。
对所有具有相同功能的类型使用类型联合是行不通的 (https://play.golang.com/p/QWE-XteWpjL)。
在特定类型的结构中嵌入容器确实有效(https://play.golang.com/p/j0AR48Mto-a)但需要使用接口(interface),这意味着 Less
和 Val
在示例函数中不能内联。如果类型联合中的子集之间没有清晰的描述,它也可能无法很好地工作。
最佳答案
顺便说一句,已经有一个用于排序的库
https://pkg.go.dev/golang.org/x/exp/slices#Sort
1。您可以使用泛型创建接口(interface),然后为其键入断言。
例子:
type Lesser[T SupportedType] interface {
Less(T) bool
}
type Vec[T SupportedType] []T
func (vec Vec[T]) Less(a, b int) bool {
return any(vec[a]).(Lesser[T]).Less(vec[b])
}
func main() {
vs := Vec[String]([]String{"a", "b", "c", "d", "e"})
vb := Vec[Bool]([]Bool{false, true})
fmt.Println(vs.Less(3, 1))
fmt.Println(vb.Less(0, 1))
}
2。您可以将类型保存在 Vec 上。
例子:
type Lesser[T SupportedType] interface {
Less(T) bool
}
type Vec[T SupportedType, L Lesser[T]] []T
func (vec Vec[T, L]) Less(a, b int) bool {
return any(vec[a]).(L).Less(vec[b])
}
func main() {
vs := Vec[String, String]([]String{"a", "b", "c", "d", "e"})
fmt.Println(vs.Less(3, 1))
}
3。嵌套类型约束
感谢@blackgreen
例子:
type SupportedType interface {
Int8 | Time | Bool | String
}
type Lesser[T SupportedType] interface {
Less(T) bool
}
type Vec[T interface {
SupportedType
Lesser[T]
}] []T
func (vec Vec[T]) Less(a, b int) bool {
return vec[a].Less(vec[b])
}
func main() {
vs := Vec[String]([]String{"a", "b", "c", "d", "e"})
fmt.Println(vs.Less(3, 1))
}
基准:
benchmark 1 : 28093368 36.52 ns/op 16 B/op 1 allocs/op
benchmark 2 : 164784321 7.231 ns/op 0 B/op 0 allocs/op
benchmark 3 : 212480662 5.733 ns/op 0 B/op 0 allocs/op
Embedding a container inside type specific structs:
benchmark 4 : 211429621 5.720 ns/op 0 B/op 0 allocs/op
哪一个最适合您,完全取决于您。但 IMO 3 号是最好的。
关于go - 在 go (1.18) 中对泛型进行多态实现的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71542373/