Go语言的切片扩容

 更新时间:2026年03月26日 09:07:25   作者:Hoffer_  
本文主要介绍了Go语言的切片扩容,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、切片

首先我们要知道切片的本质是什么?

Slice的底层数据结构(src/runtime/slice.go):

type slice struct {
    array unsafe.Pointer  // 指向底层数组的指针
    len   int             // 当前切片长度
    cap   int             // 底层数组容量
}
切片头(slice header)
+---------------------------+
| array -> 底层数组          |
| len:当前长度              |
| cap:最大容量              |
+---------------------------+
              |
              v
底层数组(underlying array)
+------+------+------+------+------+
|  1   |  2   |  3   |  ?   |  ?   |
+------+------+------+------+------+
  ^                  ^
  |                  |
起始元素           容量上限

我们可以把切片比作一本相册只有3个照片的位置 //这里的“位置”可以代指为数组的容量(cap :3)

而你手上有两张照片去放到这个相册里面 //这两张照片就是长度(len:2)

最后底层数据就是相片册类型的结构 //array就是一个指向这个相册的指针

二、扩容触发条件

在我们理解了切片是什么之后,就聊一下切片的扩容触发:

nums := make([]int{0,3})// 创建一个切片,len=0, cap=3

num = append(nums, 1)     //len=1, cap=3
num = append(nums, 2)    //len=2, cap=3
num = append(nums, 3)    //len=3, cap=3
num = append(nums, 4)     //len=4, len > cap 触发扩容

当执行 append操作时:

  • 如果当前容量(cap)足够:直接在原底层数组末尾追加元素,修改 len并返回原切片(无新内存分配)
  • 如果容量不足:触发扩容逻辑,分配新的更大的底层数组,拷贝旧数据,再追加新元素

个人见解: 其实可以把这个切片当成最多放3张照片的相片册。当我们想要放入第四张照片时,

我们的想法肯定是买一个新的相片册能放更多的照片。

至于买多大的相册(怎么扩容),Go官方给出了扩容策略,请往下看。

三、切片扩容机制

v1.18前的扩容策略(了解)

在 Go 语言 v1.18 版本之前,当执行append向 slice 底层数组追加数据。若旧容量(oldCap)小于所需的最小容量(即cap < len+num)时,会触发扩容操作,其扩容规则:

旧容量范围新容量计算规则
cap < 1024新容量 = 旧容量 × 2(按2倍扩容)
cap ≥ 1024新容量 = 旧容量 × 1.25(按1.25 倍扩容)

v1.18+扩容策略(需要掌握!!!)

用append向slice底层数组追加num个数据。当cap>= len+num时,直接在slice底层对应的数组进行操作。如果cap< len+num需要扩容:

若 newLen > 2 * oldCap,直接将容量扩容至 newLen。(newlen = len + num)

若 oldCap < 256,将容量扩容至 2 * oldCap。

若 oldCap >= 256,每次扩容为 oldcap + (oldCap + 3 * 256)/4,重复此操作直到 newcap >= newLen。

若扩容后容量溢出,则返回 newLen;否则返回计算后的 newcap。溢出会在后续逻辑触发 panic,不在此函数处理。

这里举个例子:

a := make([]int,300,300)
a = append(a,12)
fmt.Println(len(a),cap(a))

输出结果是什么?

>>301 567//len(a),cap(a)

你做对了吗?按照v1.18+的扩容机制 ,300(oldcap) > 256, 所以newcap = 300 + (300 + 3 * 256)/4 = 567。

有的人可能会说,切片扩容不是按照那个1024的阈值去判断扩容2倍/1.25倍吗?其实说的也是对的,只是依赖版本不同,切片的扩容规则也就不一样了。

但本质上版本切片扩容的逻辑就是减少扩容次数,避免浪费内存空间。

四、总结

  • 理解切片的本质
  • 清楚切片扩容的触发条件:len + 溢出数 > cap
  • 根据切片扩容机制,进行扩容:

Gov1.18前:以 1024 为阈值:cap<1024 时扩容 2 倍,cap≥1024 时扩容 1.25 倍。

到此这篇关于Go语言的切片扩容的文章就介绍到这了,更多相关Go 切片扩容内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • golang中字符串和数字转换方法

    golang中字符串和数字转换方法

    在Golang中,可以使用strconv包中的Itoa()和Atoi()函数进行字符串与数字之间的转换,Itoa()用于将数字转换为字符串,Atoi()则用于将字符串转换回数字,本文介绍golang中字符串和数字转换方法,感兴趣的朋友一起看看吧
    2024-09-09
  • Go语言实现Sm2加解密的示例代码

    Go语言实现Sm2加解密的示例代码

    本文主要介绍了Go语言实现Sm2加解密的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Go语言之重要数组类型切片(slice)make,append函数解读

    Go语言之重要数组类型切片(slice)make,append函数解读

    这篇文章主要介绍了Go语言之重要数组类型切片(slice)make,append函数用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • 详解go如何优雅的使用接口与继承

    详解go如何优雅的使用接口与继承

    Go语言中的接口和嵌套结构体是两种重要的代码设计方式,接口定义了一组方法签名,使得不同的类型能够以相同的方式进行交互,本文将给大家介绍go语言如何优雅的使用接口与继承,文中有详细的代码供大家参考,需要的朋友可以参考下
    2024-06-06
  • Go语言中validation库不能校验零值问题的解决方法

    Go语言中validation库不能校验零值问题的解决方法

    在使用 Gin 框架的时候,前后端传递数据的时候,比如使用 JSON 格式,通常会使用 ShouldBindJSON 去用结构体打 tag 绑定前端传来的 JSON 格式数据,本文给大家介绍了Go语言中validation库不能校验零值问题的解决方法,需要的朋友可以参考下
    2024-08-08
  • Go + Gin实现双Token管理员登录的示例代码

    Go + Gin实现双Token管理员登录的示例代码

    本文主要介绍了Go + Gin实现双Token管理员登录的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-07-07
  • 详解Go语言中rand(随机数)包的使用

    详解Go语言中rand(随机数)包的使用

    在Golang中,有两个包提供了rand,分别为math/rand和crypto/rand对应两种应用场景。math/rand包实现了伪随机数生成器。也就是生成 整形和浮点型;crypto/rand包实现了用于加解密的更安全的随机数生成器。本文就来和大家详细讲讲math/rand的使用
    2022-08-08
  • golang并发编程使用Select语句的实现

    golang并发编程使用Select语句的实现

    Go语言中的select语句是并发编程中的重要工具,允许Goroutine等待多个通道操作,它阻塞直至任一case可执行,可用于接收数据、实现超时机制和非阻塞通道操作,感兴趣的可以了解一下
    2024-10-10
  • golang指数运算操作

    golang指数运算操作

    这篇文章主要介绍了golang指数运算操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go设计模式之访问者模式讲解和代码示例

    Go设计模式之访问者模式讲解和代码示例

    访问者是一种行为设计模式, 允许你在不修改已有代码的情况下向已有类层次结构中增加新的行为,本文将通过代码示例给大家详细的介绍一下Go设计模式之访问者模式,需要的朋友可以参考下
    2023-08-08

最新评论