在 Go 中制作通用算法
我无法找到一种干净的方法来实现适用于任何类型的算法。
以下代码在尝试将字符串或类型化切片转换为接口时会产生错误,并且无法比较 interface{} 对象: invalid operation: result[0] > > result[n - 1] (operator > not Define on interface)
func main() {
c := Algo("abc")
//...
c := Algo([3]int{1,2,3})
//...
}
func Algo(list []interface{}) chan []interface{} {
n := len(list)
out := make(chan []interface{})
go func () {
for i := 0; i < n; i++ {
result := make([]interface{}, n)
copy(result, list)
// an actually useful algorithm goes here:
if (result[0] > result[n-1]) {
result[0], result[n-1] = result[n-1], result[0]
}
out <- result
}
close(out)
}()
return out
}
虽然这很痛苦(我认为它应该是自动的),但我可以手动将类型切片装箱和取消装箱到接口{}中,这是上面的真正问题是比较。而且它变得越来越混乱。
a := [3]int{1,2,3}
b := make([]interface{}, len(a))
for i, _ := range a {
b[i] = a[i]
}
我什至想过使用 vector.Vector,但很多人说永远不要使用它们。
那么我应该对 int 切片和字符串实现相同的算法吗? myObject 的切片怎么样?我可以使用自定义比较函数创建一个接口,但是如何使其与标准类型一起工作?
I can't figure out a clean way to implement an algorithm that will work on any type.
The following code will produce errors trying to convert a string or a typed slice into interfaces, and you can't compare interface{} objects: invalid operation: result[0] > result[n - 1] (operator > not defined on interface)
func main() {
c := Algo("abc")
//...
c := Algo([3]int{1,2,3})
//...
}
func Algo(list []interface{}) chan []interface{} {
n := len(list)
out := make(chan []interface{})
go func () {
for i := 0; i < n; i++ {
result := make([]interface{}, n)
copy(result, list)
// an actually useful algorithm goes here:
if (result[0] > result[n-1]) {
result[0], result[n-1] = result[n-1], result[0]
}
out <- result
}
close(out)
}()
return out
}
Although it's a pain (I think it should be automatic), I can manually box and unbox typed slices into interface{}s, the real problem above is the comparison. And it just keeps getting more and more kludgy.
a := [3]int{1,2,3}
b := make([]interface{}, len(a))
for i, _ := range a {
b[i] = a[i]
}
I've even thought of using vector.Vector, but so many people say never to use them.
So should I just implement the same algorithm for int slices and strings? What about slices of myObject? I can make an interface with a custom comparison func, but then how do I make it work with standard types?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以在 Go 中使用接口来完成此操作。采用接口类型的函数是通用的,因为它不关心底层具体类型的数据表示。它通过方法调用完成所有事情。
为了制作算法的通用版本,您必须确定算法所需的数据对象的所有功能,并且必须定义抽象这些功能的方法。抽象方法签名成为接口的方法集。
为了使类型与这种泛型算法兼容,您可以在类型上定义方法来满足算法参数的接口。
我将采用您的示例代码并展示一种执行此操作的方法。大多数所需的功能恰好都被 sort.Interface 涵盖了,所以我选择嵌入它。只需要另一种功能,即制作数据副本。
下面是根据您的示例代码编写的完整工作程序。
You can do this in Go using interfaces. A function that takes an interface type is generic in the sense that it doesn't care about the data representation of the underlying concrete type. It does everything through method calls.
To make a generic version of your algorithm then, you have to identify all of the capabilities that the algorithm requires of the data objects and you have to define methods that abstract these capabilities. The abstract method signatures become method sets of interfaces.
To make a type compatible with this kind of generic algorithm, you define methods on the type to satisfy the interface of the algorithm parameter.
I'll take your example code and show one way to do this. Most of the required capabilities happen to be covered by sort.Interface so I chose to embed it. Only one other capability is needed, one to make a copy of the data.
Below is a complete working program made from your example code.
由于 Go 编程语言目前不支持泛型类型,因此这将很难做到。
查看 Go sort 包,了解它如何通过定义sort.Interface 类型,包含 Len、Less 和 Swap 方法。
Since the Go Programming Language doesn't currently support generic types, this is going to be hard to do.
Look at the Go sort package to see how it handles comparisons and other operations specific to a type by defining the sort.Interface type with Len, Less, and Swap methods.
Go 没有泛型类型,但您可以查看 sort 的工作原理来找到解决方法。他们所做的是创建一个像这样的界面:
现在,对于任何自定义类型,您都可以创建相应的可排序的自定义集合类型。排序算法只需处理整数和布尔值,因此不需要查看或关心底层数据类型是什么。
Go does not have generic types, but you can take a look at how sort works to find a workaround. What they do is create an interface like this:
And now for any custom type you can make a corresponding custom collection type that can be sorted. The sort algorithm only has to deal with integers and booleans, and so doesn't see or care what the underlying data types are.