切片的切片类型

huangapple go评论89阅读模式
英文:

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

huangapple
  • 本文由 发表于 2011年10月9日 19:46:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/7703251.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定