go slice扩容是怎么计算大小的


写在前面

面试过程中经常会被问到有没有看过go的源码,如果没有看过那面试效果就大打折扣了,这个问题如何解决呢?

首先问有没有看过go的源码,一般就是想问有没有看过go的slice,map,channel的底层实现(当然还有其他的一些,比如singleflight, syncmap,sync包的WaitGroup,Mutex等等)。在面试过程中,只需要看过一个知识点的源码,是不是比说没看过强?

那看哪一个知识点呢?slice和map考察的最多,而且查考的点都是扩容。slice扩容最简单,那我们就看slice的底层源码。

slice 源码看什么

一般面试官问slice的源码是在问什么?除了扩容机制,它没有东西可问。go 1.22.1版本中的slcie实现,算上注释也才370行代码,而扩容函数只有算上注释只有30多行代码,所以我们只需要阅读这30多行的代码,就可以说看过go的源码了。

面试官:有没有看过go的源码。

答:看过一些,尤其是slice的源码,看过它的扩容机制。

这个时候面试官就会让你讲一下go slice的扩容机制了。

源码

func nextslicecap(newLen, oldCap int) int {
	newcap := oldCap
	doublecap := newcap + newcap
	if newLen > doublecap {
		return newLen
	}

	const threshold = 256
	if oldCap < threshold {
		return doublecap
	}
	for {
		// 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) >> 2

		// We need to check `newcap >= newLen` and whether `newcap` overflowed.
		// newLen is guaranteed to be larger than zero, hence
		// when newcap overflows then `uint(newcap) > uint(newLen)`.
		// This allows to check for both with the same comparison.
		if uint(newcap) >= uint(newLen) {
			break
		}
	}

	// Set newcap to the requested cap when
	// the newcap calculation overflowed.
	if newcap <= 0 {
		return newLen
	}
	return newcap
}

这段代码逻辑非常简单,希望读者能仔细阅读一下,记住这段逻辑,面试的时候有大用。

下面画个图说明一下代码逻辑

结束语

��完这段slice扩容代码,你就可以有底气的跟面试后说你看过go的源代码了


文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
  目录