Go语言,slice切片,函数参数传递与扩容原理

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为止}

参考
参考1
参考2

你可能感兴趣的:(golang底层原理,golang)