golang-切片
slice组成
slice由三个部分组成:指针、长度和容量
- 指针指向底层连续内存空间的起点
- 长度是slice中实际存放的元素的个数,可以通过下标访问
- 容量是为slice分配了足够存放n个元素的空间,在到达这个容量之前不需要扩容
type slice struct {
array unsafe.Pointer // 指向底层数组的指针
len int // 长度
cap int // 容量
}
容量一定是大于等于长度的
通过slice的数据结构定义可以看到,在传递切片的时候,对slice进行了一次值拷贝。但是内部存放的地址是相同的,所以也相当于是引用传递
初始化方式
1. 直接声明
var s []int
此时s的值为nil,不能直接使用,需要先初始化
但是可以使用append函数
2. 使用make函数初始化
分为两种方式
- 只指定长度
s := make([]int, 5)
长度一旦被指定,就代表对应的位置已经分配了元素(可以通过下标索引获取),默认为元素类型的零值
只指定长度时,默认容量和长度相等
- 指定长度和容量
s := make([]int, 5, 10)
指定长度和容量时,长度必须小于等于容量
3. 使用字面量
s := []int{1, 2, 3}
使用字面量初始化时,长度和容量都由字面量决定
如上面的例子,长度为3,容量也为3
slice初始化流程
源码位于runtime/slice.go中
func makeslice(et *_type, len, cap int) unsafe.Pointer {
// 分配内存,关心的是cap
// 根据类型大小和容量,计算需要分配的内存大小
mem, overflow := math.MulUintptr(et.size, uintptr(cap))
if overflow || mem > maxAlloc || len < 0 || len > cap {
// 内存溢出或者分配的内存过大
// 或者长度小于0或者长度大于容量
// 都会报错
panicmakeslicelen()
}
// 分配内存
return mallocgc(mem, et, true)
}
slice的截取
s := []int{1, 2, 3, 4, 5}
s1 := s[1:3] // [2, 3] 左闭右开
截取时,会生成一个新的slice,但是底层数组还是原来的数组,所以修改s1也会影响s
如果截取的长度大于容量,会报错

浙公网安备 33010602011771号