• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Go Slice的扩容机制

武飞扬头像
Voryla
帮助1

Go Slice的扩容机制

在Go语言中使用append()函数向Slice添加元素,扩容也是发生在append的调用中,当切片内部的容量,不足以容纳新增元素时就会触发Slice的扩容。

并非每次调用append()函数都会触发扩容,因为扩容涉及到内存分配,会减缓append的速度。本文将从底层分析,以展现Slice切片扩容的具体策略。

扩容机制

1.扩容时机

func SliceExpansion() {
	sliceA := make([]int, 3, 4)
	sliceA = append(sliceA, 1) // 未扩容
	fmt.Printf("SliceA len: %v, cap: %v\n", len(sliceA), cap(sliceA))
	sliceB := make([]int, 3, 3)
	sliceB = append(sliceB, 1) // 触发扩容
	fmt.Printf("SliceB len: %v, cap: %v\n", len(sliceB), cap(sliceB))
}

学新通

可见SliceA 初始len=3,初始cap=4;SliceB 初始len=3,初始cap=3,向SliceA 追加一个元素时,由于SliceA追加元素后len<cap并未发生扩容,而向SliceB 追加一个元素时,由于SliceB追加元素后len>=cap发生扩容,且扩容后容量为6,看上去好像扩容就是在原来Slice长度的基础上增加一倍容量,事实上也是如此吗?

2.扩容策略

当Slice的当前容量不足以容纳新增元素与原长度之和时会发生Slice的扩容,扩容的核心逻辑代码为 growSlice()

func growslice(et *_type, old slice, cap int) slice {

	// 将当前容量取出
	newcap := old.cap
	// 当前容量*2
	doublecap := newcap   newcap
	// cap:预估容量是否大于两倍的当前容量
	if cap > doublecap {
		// 新容量 = 预估容量
		newcap = cap
	} else {
		// 当前容量是否小于1024
		if old.cap < 1024 {
			// 两倍扩容
			newcap = doublecap
		} else {
			// Check 0 < newcap to detect overflow
			// and prevent an infinite loop.
			// 新容量 = 循环增加1.25倍,直至newcap > cap
			for 0 < newcap && newcap < cap {
				newcap  = newcap / 4
			}
			// Set newcap to the requested cap when
			// the newcap calculation overflowed.
            // 如果经过循环1.25增加,最终newcap计算值溢出,即超过了int的最大范围,则最终容量就是新申请的容量
			if newcap <= 0 {
				newcap = cap
			}
		}
	}
	............
    // 内存分配相关
    ............
	// 将原数组复制到新地址
	memmove(p, old.array, lenmem)
	// 返回新创建的结构体
	return slice{p, old.len, newcap}
}
学新通

上面代价显示了Slice扩容的核心逻辑,Go语言中切片的扩容策略为:

  • **策略一:**如果新申请的容量(cap)大于2倍的旧容量(old.cap),则最终容量(nwecap)是新申请的容量。
  • **策略二:**如果不满足策略一
    • 如果旧切片len<1024,则最终容量是就容量的2倍,即newcap = doublecap。
    • 如果旧切片len>=1024,则最终容量循环增加1.25倍,直至newcap > cap 为止。
  • **策略三:**在进行循环1.25倍计算时,最终容量计算值发生溢出,即超过了int的最大范围,则最终容量就是新申请的容量。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfbcfa
系列文章
更多 icon
同类精品
更多 icon
继续加载