切片
1.切片数据结构
Go 语言中切片数据结构在源码包 src 的 runtime/slice.go
type slice struct {
array unsafe.Pointer // 数据部分
len int // 长度
cap int // 容量
}2.切片扩容
当 Go 中切片 append 当容量超过了现有容量,就需要进行扩容
确定扩容的大小
func growslice(et *_type, old slice, cap int) slice {
// 得到旧容量大小
newcap := old.cap
// 扩容容量 = 旧容量 * 2
doublecap := newcap + newcap
// cap是新申请容量
// 如果申请容量(cap)溢出(大于doublecap),就直接申请
if cap > doublecap {
newcap = cap
// 不足,就再判断旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
} else {
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
}根据扩容大小和切片类型,确定不同的内存分配大小,同时保证内存的对齐。因此,申请的内存可能会大于实际的
et.size * newcap
最后核心是申请内存。要注意的是,新的切片不一定意味着新的地址。
切片复制
浅拷贝
先将 data 的成员数据拷贝到寄存器,然后从寄存器拷贝到 shallowCopy 的对象中。
注意到只是拷贝了指针而已, 所以是浅拷贝
深拷贝
检查切片长度与元素大小
静态分析和内存扫描
遍历内存,去复制每个元素
最后更新于