编写在“通用”数组上运行的方法的惯用方式是什么?
我有一个类型化数组:
a := make([]int, 0)
我想写一个可以对任何类型的数组进行操作的简单方法:
func reverse(a []interface{}) []interface{} {
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
return a
}
使用此方法a = reverse(a)
会给我两个错误:
cannot use a (type []int) as type []interface {} in argument to reverse
cannot use reverse(a) (type []interface {}) as type []int in assignment
答案 0 :(得分:2)
耐心!根据该语言的latest draft proposal to add type parameters,您将能够在以后的Go版本中编写这样一个通用的reverse
函数:
func reverse[T any](s []T) []T {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}
func main() {
s := []int{1, 2, 3, 4, 5}
s = reverse(s)
fmt.Println(s)
}
答案 1 :(得分:2)
并不是说您现在就可以在生产中使用泛型(从2020年10月2日开始),但是对于对即将到来的go泛型功能感兴趣的人来说,最新的design draft是go,您可以编写泛型函数{ {1}}如下
reverse
输出:
package main
import (
"fmt"
)
func reverse[T any](s []T) []T {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}
func main() {
s := []int{1, 2, 3, 4, 5}
s = reverse(s)
fmt.Println(s)
}
答案 2 :(得分:1)
直到泛型出现(很可能称为contracts),反射和接口是实现这种泛化的唯一工具。
您可以定义reverse()
来获取interface{}
的值,并使用reflect
包对其进行索引并交换元素。这通常很慢,并且很难阅读/维护。
接口提供了一种更好的方法,但是需要您将方法编写为不同的类型。看一下sort
包,特别是sort.Sort()
函数:
func Sort(data Interface)
sort.Interface
在哪里:
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
sort.Sort()
可以对实现sort.Interface
的任何切片进行排序,这些切片具有排序算法执行其工作所需的方法。这种方法的优点在于,您不仅可以对切片(例如,链表或数组)进行排序,还可以对其他数据结构进行排序。