3

编写对“通用”数组进行操作的方法的惯用方法是什么?

我有一个类型化数组:

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
4

3 回答 3

3

在泛型出现之前(很可能称为协定),反射和接口是实现这种泛化的唯一工具。

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

于 2019-06-20T07:27:54.383 回答
3

并不是说您现在(截至 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]
于 2020-10-04T02:12:22.897 回答
1

耐心!根据在语言中添加类型参数的最新提案草案,您将能够reverse在 Go 的未来版本中编写这样的通用函数:

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)
}

操场

于 2020-06-25T16:06:15.463 回答