【问题标题】:Go slice length is capacity -1, why?切片长度是容量-1,为什么?
【发布时间】:2015-10-19 13:24:30
【问题描述】:

考虑下面的 go 代码:

fruits := [4]string{"apple", "orange", "mango"}
tasty_fruits := fruits[1:3]
fmt.Println(len(tasty_fruits))
fmt.Println(cap(tasty_fruits))
fmt.Println(tasty_fruits)

输出:

2
3
[orange mango]

我不明白为什么taste_fruits 的容量是3,直觉上我希望它是2,因为那是切片的长度?

如果taste_fruits 的容量是3,为什么会这样:

tasty_fruits[2] = "nectarine"

结果:

panic: runtime error: index out of range

【问题讨论】:

标签: arrays go slice


【解决方案1】:

这一行:

fruits := [4]string{"apple", "orange", "mango"}

创建一个数组,而不是一个切片。即使您只提供了 3 个元素,它也有 4 个元素。fmt.Printf("%q", fruits) 的输出:

["apple" "orange" "mango" ""]

切片:

tasty_fruits := fruits[1:3]

结果:

["orange" "mango"]

长度:显然是 2。容量?

容量是...切片长度与切片外[底层]数组长度之和。

由于在底层数组中"mango" 之后有一个元素,因此容量为2 + 1 = 3

索引切片 (tasty_fruits):规范:Index expressions:

对于切片类型Saa[x]

  • 如果x 在运行时超出范围,则会发生运行时恐慌

如果0 <= x < len(a)x 在范围内,否则超出范围。由于len(tasty_fruits)2,索引2 超出范围,因此会出现运行时恐慌。

您不能对超出切片长度的切片进行索引,即使容量允许也是如此。如果重新切片切片,则只能到达超出长度的元素,例如:

tasty_fruits2 := tasty_fruits[:3]
tasty_fruits2[2] = "nectarine" // This is ok, len(tasty_fruits2) = 3
fmt.Printf("%q", tasty_fruits2)

输出:

["orange" "mango" "nectarine"]

【讨论】:

    【解决方案2】:

    切片的容量取决于底层数组的大小。 因此,如果您将fruits 更改为具有不同大小,例如:

    fruits := [5]string{"apple", "orange", "mango"}
    

    cap(tasty_fruits) 将返回 4 而不是 3。

    所以容量意味着切片的最大尺寸可以扩展到。 “切片不能超出其容量。尝试这样做会导致运行时恐慌”。

    切片本质上是带有边界检查的c 指针。切片的长度是它将在运行时检查的边界。因此,如果您尝试访问超出长度的任何内容,也会导致运行时恐慌。

    是的,长度

    更多详情请阅读Go Slices: usage and internals

    【讨论】:

      【解决方案3】:

      如此处所述:http://blog.golang.org/slices "Capacity 字段记录了底层数组实际拥有的空间;它是 Length 可以达到的最大值。尝试将切片增长到超出其容量将超出数组的限制并会引发恐慌。”

      【讨论】:

        【解决方案4】:

        您正在创建容量为 3 的切片(因为 [1:3] 可能包含 3 个元素:1,2 和 3)。但是由于您从中复制的切片不包含 3 上的元素,因此仅复制了 1 和 2。

        【讨论】:

        • 切片复制元素。并且源是一个数组,而不是一个切片,并且数组确实有4个元素。看我的回答。
        猜你喜欢
        • 2016-08-09
        • 2020-04-25
        • 2011-10-28
        • 1970-01-01
        • 1970-01-01
        • 2020-07-11
        • 1970-01-01
        • 1970-01-01
        • 2017-06-19
        相关资源
        最近更新 更多