Slice of slices types

TypesGoSlice

Types Problem Overview


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.

Types Solutions


Solution 1 - Types

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

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionharmView Question on Stackoverflow
Solution 1 - TypespeterSOView Answer on Stackoverflow
Solution 2 - TypesjimtView Answer on Stackoverflow