私は現在、優れた Tour of Go に取り組んでいます。次の解決策で演習の1つ(#45)を終了しました。
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
}
uint8
タイプのmake
ステートメントを2回使用する必要がある理由がわかりません(スニペットのコメントを参照)。それは冗長に思えますが、他の方法でそれを行う方法がわかりません。
Goでこれを行う方法は他にありません。
はい、冗長ですが必要です。 2番目のmake()ステートメントは、最初のステートメントから完全に独立しています。コンパイラはpic[i]
から型を推測できるはずだと主張できますが、現時点ではそうではありません。
もう1つのポイント:2番目のケースで型を省略した場合、make()ステートメントはどのように見えますか? make()は、実際の割り当てを行い、必要なlen/capacityを指定できるようにするために必要です。
補足として、スライスの長さを混ぜました。この演習では、コードに入れるとき、dy
ではなく、dx
の長さをトップレベルスライスに設定する必要があります。
明示的にするために、括弧を使用して_[][]uint8
_を[]([]uint8)
として書き換えることができます:(_uint8
_型のスライス)のスライス。
make 組み込み関数を使用すると、タイプT
のスライスに対して、make(T, n)
は、長さT
のタイプn
のスライスを返し、容量n
。
したがって、make([][]uint8, 2)
はmake([]([]uint8), 2)
と同等であり、_2
_型のスライスの長さと容量が_uint8
_のスライスを返します。タイプ_uint8
_はそのゼロ値(長さと容量がゼロのnil
参照)に初期化されます。
多次元スライスはギザギザで、多次元 ギザギザ配列 に類似しています。
例えば、
_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))
}
}
_
出力:
_ss: [][]uint8 [[] []] 2
ss[0]: []uint8 [] 0
ss[1]: []uint8 [] 0
_