切片slice是golang中非常经典的数据结构,其定位可以类比其他语言中的动态数组。 切片中的元素存放在一块内存地址连续的区域,使用索引可以快速检索到指定位置的元素;切片长度和容量是可变的,在使用过程中可以根据需要进行扩容。
本文对应的Golang版本是1.21.9
数据结构
// src/runtime/slice.go
type slice struct {
array unsafe.Pointer
len int
cap int
}
array 指针指向底层数组, len表示切片长度,cap表示底层数组容量。
初始化
声明和初始化主要通过 1) 变量声明 2) 字面量 3) 使用内置函数make() 4) 从切片和数组中切取
func makeslice(et *_type, len, cap int) unsafe.Pointer {
mem, overflow := math.MulUintptr(et.Size_, uintptr(cap))
if overflow || mem > maxAlloc || len < 0 || len > cap {
mem, overflow := math.MulUintptr(et.Size_, uintptr(len))
if overflow || mem > maxAlloc || len < 0 {
panicmakeslicelen()
}
panicmakeslicecap()
}
return mallocgc(mem, et, true)
}
- 调用 math.MulUintptr 的方法,结合每个元素的大小以及切片的容量,计算出初始化切片所需要的内存空间大小。
- 如果容量超限,len 取负值或者 len 超过 cap,直接 panic
- 调用位于 runtime/malloc.go 文件中的 mallocgc 方法,为切片进行内存空间的分配
元素追加
a := []int{
1,2,3,4,5}
b := a[1:4]
b = append(b, 10) // 此时元素a[4]将由5变成0
此时需要借助扩展表达式 (完整切片表达式)
a := []int