之前看过一个面试题,面试题是这样势的
package main
import "fmt"
func main() {
a1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
a2 := a1[3:6]
a3 := a2[2:4]
fmt.Println(a2, a3)
}
输出什么,先别着急去跑脚本,带着自己的答案看下去
a2的输出 不用说了,前闭后开所以是[4,5,6],那么a2呢
如果变成这样呢
package main
import "fmt"
func main() {
a1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
var a2 []int = make([]int,1,1)
fmt.Println(len(a2),cap(a2))
a2 = a1[3:6]
a3 := a2[2:4]
fmt.Println(a2, a3)
fmt.Println(len(a2),cap(a2))
fmt.Println(len(a3),cap(a3))
}
又会输出什么呢?
我们先这个
1 1
[4 5 6] [6 7]
3 6
2 4
看到这就很疑惑了,怎么a2的cap是6,a3的容量是4呢
我们看下 slice的数据结构
type slice struct {
array unsafe.Pointer
len int
cap int
}
The array underlying a slice may extend past the end of the slice. The capacity is a measure of that extent: it is the sum of the length of the slice and the length of the array beyond the slice; a slice of length up to that capacity can be created by slicing a new one from the original slice.
Go spec对于其中的low和high这两个索引的取值范围也做了明确的说明。
For arrays or strings, the indices are in range if 0 <= low <= high <= len(a), otherwise they are out of range. For slices, the upper index bound is the slice capacity cap(a) rather than the length
本文的例子是在slice的基础上做切片操作,所以要看上面这段话的最后一句。也就是high的上限是slice的容量,而不是长度。所以再看本文开头的例子中a3,high的值是4,超过了a2的长度(3),但小于a2的容量(6)。所以并没有越界。所以最后a3的输出是"[6 7]"。
大概意思
应用切片下面的数组可以扩展到片的末端。容量是对该范围的度量:它是切片的长度和超出切片的数组长度的总和;可以通过从原切片中切出一个新的切片来创建长度达到该容量的切片。
意思就是slice的容量是"自身的长度"与"超出其长度范围的底层数组的长度"之和。
有了这个结论 我们来看下
刚才的结果
1 1
[4 5 6] [6 7]
3 6
2 4
也就可以理解容量问题了,
然后再看a2的引用是3,6 值是4 5 6,但是为什么a3会是[6 7]呢
别忘了 他们引用的都是a1,a2的cap是6 自然是到a1的最后,a2 和a3的底层都是a1
那么也就可以理解了