我正在努力完成优秀的Tour of Go。 我使用以下解决方案完成了其中一个练习(#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
}
我不明白为什么我必须两次使用make
类型的uint8
语句(请参阅代码段中的注释)。这似乎是多余的,但我无法弄清楚如何以另一种方式做到这一点。
答案 0 :(得分:33)
为明确起见,我们可以使用括号将[][]uint8
重写为[]([]uint8)
:一片(类型uint8
的切片)。
使用make内置函数,对于T
类型的切片,make(T, n)
会返回长度为T
且容量为n
的切片n
。
因此,make([][]uint8, 2)
相当于make([]([]uint8), 2)
,它返回一个类型为2
的切片的长度和容量为uint8
的切片,其中每个切片类型uint8
被初始化为零值(nil
引用,其长度和容量为零)。
多维切片呈锯齿状,类似于多维jagged arrays。
例如,
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
答案 1 :(得分:31)
Go中没有其他方法可以做到这一点。
是的,我同意这是冗长的,但却是必要的。第二个make()语句完全独立于第一个。可以说,编译器应该能够从pic[i]
推断出类型,但此时并不是这样。
另一点:如果在第二种情况下省略了类型,make()语句将如何显示? make()仍然需要进行实际分配,并能够指定所需的len / capacity。
作为旁注,您混合了切片长度。该练习指出顶级切片的长度应为dy
,而不是dx
,因为您放入了代码。