【问题标题】:Slice of slices types切片类型
【发布时间】:2011-12-03 22:23:08
【问题描述】:

我目前正在努力完成出色的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 类型的make 语句两次(参见sn-p 中的cmets)。这似乎是多余的,但我无法弄清楚如何以其他方式做到这一点。

【问题讨论】:

  • 可以说,可以在开头给pic 提供dx*dy 的容量,第二行是pic := make([][]uint8, dy, dx*dy)。通过一次分配所需的内存来提高性能吗?

标签: types go slice


【解决方案1】:

明确地说,我们可以使用括号将[][]uint8 重写为[]([]uint8):(uint8 类型的切片)。

使用make 内置函数,对于T 类型的切片,make(T, n) 返回一个T 类型的切片,长度为n,容量为n

因此,make([][]uint8, 2) 等价于make([]([]uint8), 2),它返回uint8 类型切片的长度和容量为2 的切片,其中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

【讨论】:

  • 感谢锯齿状数组的链接!
【解决方案2】:

在 Go 中没有其他方法可以做到这一点。

是的,我同意这很冗长,但很有必要。第二个 make() 语句完全独立于第一个。可以说编译器应该能够从pic[i] 推断出类型,但目前还不能。

另外一点:如果你在第二种情况下省略了类型,make() 语句会是什么样子? make() 仍然需要进行实际分配并能够指定所需的长度/容量。

作为旁注,您混淆了切片长度。练习表明顶级切片的长度应为dy,而不是您在代码中输入的dx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-27
    • 2021-10-22
    • 2014-08-13
    • 2016-05-25
    • 2013-10-23
    • 1970-01-01
    • 2022-01-20
    • 2015-05-15
    相关资源
    最近更新 更多