如何编写反转任何切片的方法



编写在"泛型"数组上运行的方法的惯用方法是什么?

我有一个类型化数组:

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)给我 2 个错误:

cannot use a (type []int) as type []interface {} in argument to reverse
cannot use reverse(a) (type []interface {}) as type []int in assignment

并不是说您现在可以在生产中使用泛型(截至 2020 年 10 月 2 日(,但对于对即将推出的 Go 泛型功能感兴趣的人,借助 Go 的最新设计草案,您可以编写一个泛型函数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)
}

输出:

[5 4 3 2 1]

在泛型到来(很可能被称为合约(之前,反射和接口是实现这种泛化的唯一工具。

您可以定义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的切片进行排序,任何具有排序算法完成其工作所需的方法的切片。这种方法的好处是,您也可以对其他数据结构进行排序,而不仅仅是切片(例如链表或数组(,但通常使用切片。

耐心!根据向语言添加类型参数的最新提案草案,您将能够在未来版本的 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)
}

(游乐场(

<小时 />

出于性能原因,您可能需要就地反转切片:

package main
import "fmt"
func reverse[T any](s []T) {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
}
func main() {
    s := []int{1, 2, 3, 4, 5}
    reverse(s)
    fmt.Println(s)
}

(游乐场(

最新更新