GoLang:返回任何类型的2D切片

3
我知道如何创建这样的2D切片。
var data []int
data = make([]int, w*h)
v := make([][]int, h)
for i := 0; i < h; i++ {
    v[i] = data[w*i : w*(i+1)]
}

由于这段代码非常冗长且将会创建许多同样的代码,我决定将其重构为一个函数。

func create2dSlice(w, h int) [][]int {
    var data []int
    data = make([]int, w*h)
    v := make([][]int, h)
    for i := 0; i < h; i++ {
        v[i] = data[w*i : w*(i+1)]
    }
    return v
}

func main() {
    a := create2dSlice(3, 2)
}

这仅适用于整数。在golang中是否有任何方法可以重用相同的代码来处理其他类型?

我来自C ++,我希望能够做到类似这样的事情。

create2dSlice<int>(w, h)

5
Go语言没有泛型。 - u_mulder
你可以在谷歌上搜索“golang泛型”,找到一个合适的解决方案。 - u_mulder
你需要多少种不同类型的二维切片?如果你只需要特定数量,最好只编写指定数量的函数作为这些类型的二维切片生成器。 - Jonathan
3个回答

4

Go语言没有泛型。对于矩阵等类似问题,我在snippet文件夹中的matrix.go文件中有一个NewMatrix函数。设计上,我可以简单地复制它,并将[]int全局替换为另一种类型,例如[]float64

您可以通过给w片段分配有效容量来改进函数。

例如,

package main

import "fmt"

func NewMatrix(r, c int) [][]int {
    a := make([]int, c*r)
    m := make([][]int, r)
    lo, hi := 0, c
    for i := range m {
        m[i] = a[lo:hi:hi]
        lo, hi = hi, hi+c
    }
    return m
}

func create2dSlice(w, h int) [][]int {
    a := make([]int, w*h)
    s := make([][]int, h)
    lo, hi := 0, w
    for i := range s {
        s[i] = a[lo:hi:hi]
        lo, hi = hi, hi+w
    }
    return s
}

func main() {
    r, c := 2, 3
    m := NewMatrix(r, c)
    fmt.Println(m)
    w, h := c, r
    a := create2dSlice(w, h)
    fmt.Println(a)
}

输出:

[[0 0 0] [0 0 0]]
[[0 0 0] [0 0 0]]

The Go Programming Language Specification

Slice expressions

Slice expressions construct a substring or slice from a string, array, pointer to array, or slice. There are two variants: a simple form that specifies a low and high bound, and a full form that also specifies a bound on the capacity.

Full slice expressions

For an array, pointer to array, or slice a (but not a string), the primary expression

a[low : high : max]

constructs a slice of the same type, and with the same length and elements as the simple slice expression a[low : high]. Additionally, it controls the resulting slice's capacity by setting it to max - low.


为什么要使用make创建长度为c*ra切片?直接在循环内部创建长度为c的切片不是更简单吗?或者说多次调用make会有问题吗? - Le garcon
1
@Legarcon:代码量并不重要,性能(CPU时间、分配的字节数和分配次数)才是关键。调用make会产生成本,多次调用make会产生更多成本。这里有一个性能基准测试(PeterSO)与较少代码(LeGarcon)的比较:garcon_test.go:https://play.golang.org/p/wY53-UNxKdT。还有更好的[引用局部性](https://en.wikipedia.org/wiki/Locality_of_reference)。 - peterSO

0

只需两个方法即可提供int或string 2d切片。Golang没有泛型。


真可惜 :-( - tuket

0

稍微详细解释一下。Go要求你这样做的原因是因为这样可以让代码更清晰易懂。在平衡代码清晰度和代码重复性时,Go更倾向于清晰度。很多语言会选择“不重复代码”的一面,但清晰度会受到牺牲。不过如果确实很重要,你还有几个选项: 1. 为所有可能的返回类型制作一个接口。例如,你可以返回[][]Number。 2. 制作一个包含传输方法的二维数组的结构体,即NumberArray.AsInts()。 3. 返回空接口并使用反射。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接