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