英文:
Slice of slices types
问题
我目前正在学习优秀的Go之旅。我用以下解决方案完成了其中一个练习(#45):
func Pic(dx, dy int) [][]uint8 {
pic := make([][]uint8, dy) /* 类型声明 */
for i := range pic {
pic[i] = make([]uint8, dx) /* 再次声明类型? */
for j := range pic[i] {
pic[i][j] = uint8((i+j)/2)
}
}
return pic
}
我不明白为什么我必须使用两次make
语句和uint8
类型(请参见代码片段中的注释)。这似乎是多余的,但我无法找出其他方法。
英文:
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.
答案1
得分: 38
为了明确起见,我们可以使用括号将[][]uint8
重写为[]([]uint8)
:一个类型为uint8
的切片的切片。
使用内置函数make,对于类型为T
的切片,make(T, n)
返回一个类型为T
、长度为n
、容量为n
的切片。
因此,make([][]uint8, 2)
等同于make([]([]uint8), 2)
,它返回一个切片,长度和容量都为2
,其中每个类型为uint8
的切片都被初始化为其零值(长度和容量都为零的nil
引用)。
多维切片是不规则的,类似于多维jagged arrays。
例如,
package main
import "fmt"
func main() {
ss := make([][]uint8, 2) // ss是[]([]uint8)
fmt.Printf("ss: %T %v %d\n", ss, ss, len(ss))
for i, s := range ss { // s是[]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
英文:
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
答案2
得分: 35
在Go中没有其他方法可以做到这一点。
是的,我同意这很冗长,但是必要的。第二个make()语句完全独立于第一个。可以说编译器应该能够从pic[i]
推断出类型,但目前还不能。
另一个问题是:如果在第二种情况下省略了类型,make()语句会是什么样子?make()仍然需要进行实际的分配,并能够指定所需的长度/容量。
另外,你混淆了切片的长度。练习中指定顶层切片的长度应为dy
,而不是你在代码中写的dx
。
英文:
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.
答案3
得分: 0
你可以像这样初始化切片的切片:
matrix2D := [][]int8{
{1, 2, 3},
{4, 5, 6},
}
fmt.Println(matrix2D) // [[1 2 3] [4 5 6]]
英文:
You can initialize slice of slices like that:
matrix2D := [][]int8{
{1, 2, 3},
{4, 5, 6},
}
fmt.Println(matrix2D) // [[1 2 3] [4 5 6]]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论