Slice of slices types
I'm currently working my way through the excellent Tour of Go. I finished one of the exercises (#45) with the following solution:
func Pic(dx, dy int) [][]uint8 {
pic := make([][]uint8, dy) /* type declaration */
for i := range pic {
pic[i] = make([]uint8, dx) /* again the type? */
for j := range pic[i] {
pic[i][j] = uint8((i+j)/2)
}
}
return pic
}
I don't understand why I have to use a make
statement with the uint8
type twice (see comments in snippet). That seems redundant but I can't figure out how to do it in an other way.
Solution 1:
To be explicit, we can use parentheses to rewrite [][]uint8
as []([]uint8)
: a slice of (slices of type uint8
).
Using the make built-in function, for a slice of type T
, make(T, n)
returns a slice of type T
with length n
and capacity n
.
Therefore, make([][]uint8, 2)
is equivalent to make([]([]uint8), 2)
, it returns a slice, with length and capacity of 2
, of slices of type uint8
, where each slice of type uint8
is initialized to its zero value (a nil
reference with a length and capacity of zero).
Multi-dimensional slices are jagged and are analogous to multi-dimensional jagged arrays.
For example,
package main
import "fmt"
func main() {
ss := make([][]uint8, 2) // ss is []([]uint8)
fmt.Printf("ss: %T %v %d\n", ss, ss, len(ss))
for i, s := range ss { // s is []uint8
fmt.Printf("ss[%d]: %T %v %d\n", i, s, s, len(s))
}
}
Output:
ss: [][]uint8 [[] []] 2
ss[0]: []uint8 [] 0
ss[1]: []uint8 [] 0
Solution 2:
There is no other way to do this in Go.
Yes, I agree it is verbose, but necessary. The second make() statement is entirely independent of the first one. It could be argued that the compiler should be able to infer the type from pic[i]
, but it doesn't at this point.
Another point: how would the make() statement look if you omitted the type in the second case? The make() is still required to do the actual allocation and to be able to specify the required len/capacity.
As a side note, you mixed up the slice lengths. The exercise states the top level slice should have length dy
, not dx
as you put in your code.