切片types
我目前正在通过优秀的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 }
我不明白为什么我必须使用两次使用uint8
types的make
语句(请参阅代码段中的注释)。 这似乎是多余的,但我不知道如何以其他方式做到这一点。
在Go中没有其他方法可以做到这一点。
是的,我同意这是冗长的,但是必要的。 第二个make()语句完全独立于第一个。 有人可能会认为,编译器应该能够从pic[i]
推断出这个types,但是现在还没有。
还有一点:如果在第二种情况下省略了types,那么make()语句将会如何呢? make()仍然需要做实际的分配,并能够指定所需的len /容量。
作为一个侧面说明,你混合了切片的长度。 练习说明顶级切片应该有长度dy
,而不是放在代码中的dx
。
明确的说,我们可以用括号把[][]uint8
改写为[]([]uint8)
:一片( uint8
types的片)。
使用make内置函数,对于T
型片段, make(T, n)
返回长度为n
,容量为n
T
型片段。
因此, make([][]uint8, 2)
等同于make([]([]uint8), 2)
,它返回长度和容量为2
的slicetypes为uint8
的片段,其中片段typesuint8
被初始化为零值(一个长度和容量为零的nil
参考)。
多维切片是锯齿状的,类似于多维锯齿状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