Go slice length is capacity -1, why?

*爱你&永不变心* 提交于 2020-01-03 03:49:04

问题


Consider the go code below:

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]

What I don't understand is why is the capacity of tasty_fruits 3, intuitively I would expect it to be 2 since that is the length of the slice?

And if the capacity of tasty_fruits is 3 why does:

tasty_fruits[2] = "nectarine"

result in:

panic: runtime error: index out of range

回答1:


This line:

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

Creates an array, not a slice. It has 4 elements even though you only supplied 3. Output of fmt.Printf("%q", fruits):

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

Slicing it:

tasty_fruits := fruits[1:3]

Results in:

["orange" "mango"]

Length: obviously 2. Capacity?

The capacity is ... the sum of the length of the slice and the length of the [underlying] array beyond the slice.

Since there is one element after "mango" in the underlying array, capacity is 2 + 1 = 3.

Indexing the slice (tasty_fruits): spec: Index expressions:

For a of slice type S: a[x]

  • if x is out of range at run time, a run-time panic occurs

x is in range if 0 <= x < len(a), otherwise it is out of range. Since len(tasty_fruits) is 2, the index 2 is out of range, and therefore runtime panic occurs.

You can't index the slice beyond the length of the slice, even if capacity would allow it. You can only reach the elements beyond the length if you reslice the slice, e.g.:

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

Output:

["orange" "mango" "nectarine"]



回答2:


The capacity of a slice depends on the size of the underlying array. So if you change fruits to have a difference size, for example:

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

cap(tasty_fruits) will return 4 instead of 3.

So capacity means the maximum size of the slice can be extended to. "A slice cannot be grown beyond its capacity. Attempting to do so will cause a runtime panic".

And slices are essentially c pointers with boundary check. The length of a slices, is the boundary it will check during run time. As a result, if you try to access anything beyond length, a runtime panic will also be caused.

And yes length <= capacity is always true.

For more details please read Go Slices: usage and internals




回答3:


As documented here: http://blog.golang.org/slices "The Capacity field records how much space the underlying array actually has; it is the maximum value the Length can reach. Trying to grow the slice beyond its capacity will step beyond the limits of the array and will trigger a panic."




回答4:


You are creating a slice with the capacity of 3 (because [1:3] could contain 3 elements: 1,2 and 3). But as the slice you are copying from does not contain an element on 3, only 1 and 2 are copied.



来源:https://stackoverflow.com/questions/31685620/go-slice-length-is-capacity-1-why

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!