考虑下面的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)
OUPUTS:
2
3
[orange mango]
我不明白为什么Tasty_fruits 3的容量,直觉上我会期望它是2,因为这是切片的长度?
如果tasty_fruits的容量是3,为什么:
tasty_fruits[2] = "nectarine"
结果:
panic: runtime error: index out of range
答案 0 :(得分:9)
这一行:
fruits := [4]string{"apple", "orange", "mango"}
创建数组,而不是切片。它有4个元素,即使你只提供了3. fmt.Printf("%q", fruits)
的输出:
["apple" "orange" "mango" ""]
切片:
tasty_fruits := fruits[1:3]
结果:
["orange" "mango"]
长度:显然2.容量?
容量是...切片长度与切片之外的[基础]数组长度之和。
由于基础数组中"mango"
之后有一个元素,因此容量为2 + 1 = 3
。
为切片(tasty_fruits
)编制索引:spec:Index expressions:
对于
a
切片类型S
:a[x]
- 如果
x
在运行时超出范围,则会发生运行时恐慌
x
在0 <= x < len(a)
范围内,否则超出范围。由于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"]
答案 1 :(得分:0)
切片的容量取决于底层数组的大小。
因此,如果您将fruits
更改为具有差异大小,例如:
fruits := [5]string{"apple", "orange", "mango"}
cap(tasty_fruits)将返回4而不是3.
因此容量意味着切片的最大尺寸可以扩展到。 &#34;切片不能超出其容量。试图这样做会导致运行时恐慌&#34;。
切片基本上是带有边界检查的c
指针。切片的长度是它在运行时检查的边界。因此,如果您尝试访问超出长度的任何内容,也会导致运行时出现紧急情况。
是的长度&lt; =容量总是如此。
有关详情,请参阅Go Slices: usage and internals
答案 2 :(得分:-1)
如此处所述:http://blog.golang.org/slices&#34;容量字段记录底层数组实际拥有的空间大小;它是长度可以达到的最大值。试图使切片超出其容量将超出阵列的极限并引发恐慌。&#34;
答案 3 :(得分:-2)
您正在创建容量为3的切片(因为[1:3]可能包含3个元素:1,2和3)。但是,由于要复制的切片不包含3上的元素,因此仅复制1和2。