GoLang:返回任意类型的2d切片

I know how to create a 2D slice like this.

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

Since this is very verbose and I'm going to create many of these, I decided to refactor it into a function.

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

This works only for integers. It there any way in golang to do this for other types reusing the same code?

I come from C++ and I would expect to be able to do something like this.

create2dSlice<int>(w, h)

Go doesn't have generics. For matrices, a similar problem, I have a NewMatrix function in a matrix.go file in my snippet folder. By design, I can simply copy it and do a global change of []int to another type, for example, []float64.

You could improve your function by giving w slices a valid capacity.

For example,

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

Output:

[[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.

Just have two methods that give you an int or a string 2d slice. Golang has no generics.

To go in to this a little more. The reason Go wants you to type this out is because it makes code more clear. When balancing code clarity and code repetition, Go sides with clarity. Many languages take the 'no repeated code' side of this balance, but reduced clarity is a tradeoff. You do have a few options though if it's super important. 1. Make an interface for all the possible return types. You could return [][]Number for example. 2. Make a struct that wraps the 2d array that has transfer methods, i.e. NumberArray.AsInts() 3. Return the empty interface and use reflection.