Go语言,slice切片,函数参数传递与扩容原理
一 、源码
type slice struct {
array unsafe.Pointer
len int
cap int
}
1.指针array,指向底层数组中切片指定的开始位置
2.长度len,即切片的长度
3.容量cap,也就是最大长度,即切片开始位置到数组的最后位置的长度
二、切片作为函数参数时
切片作为函数参数时是值传递,会复制一份副本过去。
如果改变原有数据,原切片数据是否会发生变化:会!
原因:尽管是值传递,但因为切片的第一个成员为指针,和原切片指向同一位置,所以会改变。
如果使用append追加数据,原切片数据是否会改变:不会!
原因:append()函数返回值为新的切片,新的切片的指针、len、cap,并不影响原切片的指针、len、cap,所以原切片不会变长,不会追加新的元素,原切片不会改变。
如果使用append()返回的新切片,改变这个新切片的前一部分数据(老数据,追加前的数据),原切片可能发生改变,因为扩容后的新切片如果是在原位置扩容,指针指向的起始位置没有改变,那么就会。
如果扩容后的新切片指针指向了新的起始位置,那么就不会。
扩容原理,附源码
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
const threshold = 256
if old.cap < threshold {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
// Transition from growing 2x for small slices
// to growing 1.25x for large slices. This formula
// gives a smooth-ish transition between the two.
newcap += (newcap + 3*threshold) / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
初始化newcap=old.cap
如果所需容量大于原容量二倍,扩为所需容量
否则:{ 如果原容量小于256,扩为原容量的二倍,否则循环按照newcap+=(newcap+3*256)/4,直到newcap>=cap为止}
本文深入探讨Go语言中切片的内部结构,详细解析其作为函数参数时的行为,以及append操作对切片的影响。重点阐述了切片扩容的源码实现,包括初始容量设置、不同扩容策略及其条件。通过实例分析,帮助读者理解切片在内存管理和并发安全中的关键角色。
802

被折叠的 条评论
为什么被折叠?



