当前位置: 首页 > news >正文

Go 基础丨切片 slice

1. 底层

  • runtime/slice.go

    type slice struct {array unsafe.Pointer		// 指向底层数组len   int								// 切片元素数量cap   int								// 底层数组容量
    }
    
  • reflect/value.go

    type SliceHeader struct {Data uintptrLen  intCap  int
    }
    

2. 创建

  • 根据数组创建

    s := arr[0:3]
    
  • 字面量:编译时插入创建数组的代码

    s := []int{1, 2, 3}
    
  • make:运行时创建数组

    s := make([]int, 10)
    

3. 测试

3.1 字面量创建切片底层

func main() {s := []int{1, 2, 3}fmt.Println(s)
}

查看 Plan9 汇编代码,运行:

go build -gcflags -S main.go

重点关注 s := []int{1,2,3} 对应的部分:

LEAQ    type.[3]int(SB), AX						#创建一个大小为3,类型为int的数组
PCDATA  $1, $0
NOP
CALL    runtime.newobject(SB)				  #新建一个结构体(slice)的值,并往里面塞3个数组
MOVQ    $1, (AX)
MOVQ    $2, 8(AX)
MOVQ    $3, 16(AX)

3.2 make 创建切片

func main() {s := make([]int, 3)fmt.Println(s)
}

查看 Plan9 汇编代码,运行:

go build -gcflags -S main.go

重点关注 s := make([]int, 3) 对应的部分:

LEAQ    type.int(SB), AX
MOVL    $3, BX
MOVQ    BX, CX
PCDATA  $1, $0
CALL    runtime.makeslice(SB) 		#直接调用 makeslice 方法

4. 访问

  • 下标访问
  • range 遍历
  • len 查看切片长度
  • cap 查看数组容量

5. 追加

s := []int{1, 2, 3}
s = append(s, 4, 5)

如果 append 后,len > cap,则需要做扩容。

6. 扩容

底层调用 growslice() 方法:

6.1 Go1.17 及之前的 growslice()

func growslice(et *_type, old slice, cap int) slice {// 检查...// 确定新 capnewcap := old.capdoublecap := newcap + newcapif cap > doublecap {// ① 如果新 cap 大于两倍旧 cap,则直接使用新 capnewcap = cap} else {// ② 如果新 cap 小于两倍旧 cap 且旧 cap 小于 1024,则 cap 直接翻倍if old.cap < 1024 {newcap = doublecap} else {// ③ 如果新 cap 小于两倍旧 cap 且旧 cap 大于 1024,则每次增长 25%for 0 < newcap && newcap < cap {newcap += newcap / 4}if newcap <= 0 {newcap = cap}}}// 新建数组,复制,字节对齐....
}

6.2 Go1.18 的 growslice()

func growslice(et *_type, old slice, cap int) slice {// 检查...// 确定新 capnewcap := old.capdoublecap := newcap + newcapif cap > doublecap {// ① 如果新 cap 大于两倍旧 cap,则直接使用新 capnewcap = cap} else {const threshold = 256if old.cap < threshold {// ② 如果新 cap 小于两倍旧 cap 且旧 cap 小于 256,则 cap 直接翻倍newcap = doublecap} else {// ③ 如果新 cap 小于两倍旧 cap 且旧 cap 大于 256,则增加幅度逐渐从 2x 降到 1.25x// 原始容量  			扩容系数//	 256					2.0//	 512          1.63//   1024         1.44//   2048         1.35//   4096         1.30for 0 < newcap && newcap < cap {newcap += (newcap + 3*threshold) / 4}...}}// 新建数组,复制,字节对齐....
}

总结

  • Go1.17 及以前
    • 如果 newcap 大于 2*oldcap,则直接使用 newcap
    • 否则
      • 如果 oldcap < 1024,则 2*oldcap
      • 如果 oldcap >= 1024,则 1.25*oldcap
  • Go1.18
    • 如果 newcap 大于 2*oldcap,则直接使用 newcap
    • 否则
      • 如果 oldcap < 256,则 2*oldcap
      • 如果 oldcap >= 256,则 oldcap += (oldcap + 3*256) / 4

在 Go1.18 中,优化了切片在容量较大时扩容的策略,让底层数组大小的增长更加平滑:通过减小阈值并固定增加一个常数,使得优化后的扩容的系数在阈值前后不再会出现从 2 到 1.25 的突变。该 commit 作者给出了几种原始容量下对应的“扩容系数”:

原始容量扩容系数
2562.0
5121.63
10241.44
20481.35
40961.30

PS:slice 在扩容的时候是并发不安全的,在并发访问的时候,需要加锁。

相关文章:

Go 基础丨切片 slice

1. 底层 runtime/slice.go type slice struct {array unsafe.Pointer // 指向底层数组len int // 切片元素数量cap int // 底层数组容量 }reflect/value.go type SliceHeader struct {Data uintptrLen intCap int }2. 创建 根据数组创建 s : arr[0:3]字面…...

哪个牌子充电宝好用?精选四大热门款充电宝品牌!公认好用

在当今快节奏的生活中&#xff0c;充电宝已经成为了我们日常生活中不可或缺的数码伴侣。无论是旅行、出差还是日常通勤&#xff0c;拥有一款好用的充电宝&#xff0c;能够确保我们的手机、平板等设备随时保持充足电量。然而&#xff0c;市场上充电宝品牌繁多&#xff0c;如何选…...

WPF/C#:如何将数据分组显示

WPF Samples中的示例 在WPF Samples中有一个关于Grouping的Demo。 该Demo结构如下&#xff1a; MainWindow.xaml如下&#xff1a; <Window x:Class"Grouping.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x&q…...

leetcode 200 岛屿数量

思路 就是深搜&#xff0c;将可以走到的都标为0 ##代码 class Solution {static int[][] to {{1,0},{0,1},{-1,0},{0,-1}};public int numIslands(char[][] grid) {// 深搜int result 0;for (int i 0; i < grid.length; i) {for (int j 0; j < grid[0].length; j)…...

​1:25万基础电子地图(江西版)

我们在《50幅1:25万基础电子地图&#xff08;四川版&#xff09;》和《1&#xff1a;25基础电子地图&#xff08;云南版&#xff09;》等文中&#xff0c;为你分享过四川和云南的基础电子地图。 现在我们再为你分享江西的1&#xff1a;25万基础电子地图&#xff0c;你可以在文…...

【RabbitMQ】初识 RabbitMQ

初识 RabbitMQ 1.认识 RabbitMQ1.1 介绍1. 2.使用场景1.2.1 推送通知1.2.2 异步任务1.2.3 多平台应用的通信1.2.4 消息延迟1.2.5 远程过程调用 1.3 特性 2.基本概念2.1 生产者、消费者和代理2.2 消息队列2.3 交换机2.3.1 direct2.3.2 topic2.3.3 headers2.3.4 fanout 2.4 绑定2…...

Qt QListView自定义树状导航控件

大部分的软件都有多个页面&#xff0c;这时候就需要一个导航栏控件&#xff0c;通过在导航栏中选择某一栏&#xff0c;同时显示对应的页面。 本文代码效果如下&#xff1a; 本文的导航栏控件基于大佬 feiyangqingyun 的导航栏控件博客Qt/C编写自定义控件46-树状导航栏_qt之实现…...

Java 数组的全面解析与应用

Java 中的数组是一种基础且重要的数据结构&#xff0c;用于存储相同类型的多个数据项。它提供了有效的数据组织和访问机制&#xff0c;是 Java 编程中不可或缺的部分。本文将从多个角度全面探讨 Java 数组的特性、操作和实际应用&#xff0c;帮助读者深入理解和有效利用这一数据…...

Thinkphp起名网宝宝起名网站源码

Thinkphp起名网宝宝起名网站源码 源码介绍 1.宝宝在线起名 2.八字起名&#xff0c;周易取名 3.一对一起名 5.支持手机wap 链接数据库地址&#xff1a;Application\Common\Conf 修改里面config.php数据库连接&#xff0c;导入sm.sql数据库文件即可 伪静态用thinkphp 后台…...

【解决方案】【最佳实践】React高阶组件中Refs 不会被传递的问题

大家好&#xff0c;我是DX3906。 最近遇到React高阶组件中Refs 不会被传递的问题。 在这里总结一下解决方案和解决思路&#xff1a;主要是通过从内向外和从外向内2种思路来分析解决的。 目录 前言 解决方案一&#xff1a;React.forwardRef 解决方案二&#xff1a;使用prop…...

SRAM和DRAM

1.SRAM&#xff08;静态RAM&#xff09; 把存放一个二进制位的物理器件称为存储元&#xff0c;它是存储器最基本的构件。 地址码相同的多个存储元构成一个存储单元。 存储单元的集合构成存储体。 静态RAM的存储元是用双稳态触发器&#xff08;六晶体管MOS&#xff09;来记忆…...

浅析Spring中Async注解底层异步线程池原理

一、前言 开发中我们经常会用到异步方法调用&#xff0c;具体到代码层面&#xff0c;异步方法调用的实现方式有很多种&#xff0c;比如最原始的通过实现Runnable接口或者继承Thread类创建异步线程&#xff0c;然后启动异步线程&#xff1b;再如&#xff0c;可以直接用java.uti…...

sqli-labs 靶场 less-7 第七关详解:OUTFILE注入与配置

SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它&#xff0c;我们可以学习如何识别和利用不同类型的SQL注入漏洞&#xff0c;并了解如何修复和防范这些漏洞。Less 7 SQLI DUMB SERIES-7判断注入点 进入页面中&#xff0c;并输入数据查看结果。 发现空数据提…...

AIGC新秀亮相,哪款大模型产品最得你心?

AIGC新秀亮相&#xff0c;哪款大模型产品最得你心&#xff1f; 近日&#xff0c;腾讯元宝APP的正式上线&#xff0c;为国内大模型AIGC产品市场增添了一名新成员。 这些所谓的“全能”大模型产品&#xff0c;凭借其强大的生成能力和广泛的应用场景&#xff0c;正逐渐改变我们的…...

RabbitMQ消息的可靠传输和防止消息丢失

在Spring Cloud项目中&#xff0c;为了确保RabbitMQ消息的可靠传输和防止消息丢失&#xff0c;需要考虑以下几个方面&#xff1a; 消息持久化&#xff1a;确保消息在RabbitMQ中持久化。队列持久化&#xff1a;确保队列是持久化的。发布确认&#xff1a;使用发布确认机制确保消…...

.net8系列-图文并茂手把手教你使用Nlog记录.net日志

Nlog是什么&#xff1f; NLog是一个为.NET平台设计的灵活且免费的日志记录库。它适用于包括.NET Framework、.NET Core和.NET Standard在内的多种.NET环境。 Nlog有什么好处或者特点&#xff1f; 配置灵活&#xff1a;NLog允许开发者通过配置文件&#xff08;通常是NLog.conf…...

课时158:脚本发布_简单脚本_远程执行

2.1.3 远程执行 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习 基础知识 简介 有时候&#xff0c;我们需要通过远程方式到另外一台主机进行脚本的执行 格式&#xff1a;ssh 远程主机登录用户名远程主机ip地址 "执行命令"效果 [r…...

3dmax2025能用云渲染吗?2025最新云渲染渲染100使用方法

3dmax2025还没用上云渲染&#xff1f;简单3步用上云渲染。 第一步&#xff0c;打开浏览器搜索渲染100&#xff0c;并进入下载客户端并安装 第二步&#xff0c;打开已安装的客户端进行安装&#xff0c;点击登录&#xff0c;未登录注册个账号即可&#xff08;注册账号时邀请码填…...

从零开始学GeoServer源码(一)(搭建开发环境Win10+IDEA23.3.5+jdk11+geoserver2.24.x)

搭建开发环境 参考资料 0、基础环境准备0.1、idea0.2、jdk0.3、源码 1、导入工程2、配置启动环境2.1、打开新增配置面板2.2、配置工作目录2.2.1、从常用配置中选择2.2.2、直接粘贴 2.3最终效果 3、调整源码3.1、添加maven引用3.2、注释无效代码3.3、删除测试代码 4、修改运行端…...

分类模型:MATLAB判别分析

1. 判别分析简介 判别分析&#xff08;Discriminant Analysis&#xff09; 是一种统计方法&#xff0c;用于在已知分类的样本中构建分类器&#xff0c;并根据特征变量对未知类别的样本进行分类。常见的判别分析方法包括线性判别分析&#xff08;Linear Discriminant Analysis, …...

为VS Code集成GPT-4V视觉能力:VisualChatGPTStudio实战指南

1. 项目概述&#xff1a;当ChatGPT“睁开双眼”如果你和我一样&#xff0c;是个重度依赖ChatGPT进行编程、文档撰写和头脑风暴的开发者&#xff0c;那你一定体验过它的强大与局限。它能写出漂亮的代码片段&#xff0c;解释复杂的概念&#xff0c;但当你指着屏幕上的一个错误说“…...

超高清电视普及困境解析:从技术参数到生态系统的完整思考

1. 超高清电视的“非主流”开局&#xff1a;一场始于2013年的行业迷思 如果你在2013年初的拉斯维加斯CES展上&#xff0c;听到关于“Ultra HDTV”&#xff08;超高清电视&#xff0c;后文简称UHDTV&#xff09;的喧嚣&#xff0c;感觉就像身处一场盛大的交响乐彩排现场——乐手…...

LaTeX排版避坑指南:为什么你的多图caption编号对不齐?一个案例讲清subfig、minipage和tabular的选择

LaTeX多图排版实战&#xff1a;从编号错乱到完美对齐的解决方案 第一次在学术论文中遇到多图排版问题时&#xff0c;我盯着那个歪歪扭扭的(c)编号看了整整十分钟——它本该和(a)(b)整齐排列&#xff0c;却像迷路的孩子一样缩在角落。更糟的是&#xff0c;当我引用这些子图时&am…...

别再死记硬背了!用PyTorch和TensorFlow动手实现四种池化层,直观理解它的作用

用代码可视化理解深度学习中的池化层&#xff1a;PyTorch与TensorFlow实战指南 当你第一次听说"池化层"这个概念时&#xff0c;是否也感到困惑&#xff1f;为什么神经网络需要这样一个"缩小"图像的层&#xff1f;本文将通过PyTorch和TensorFlow两种框架的实…...

别再死记公式了!用复平面几何法直观理解Biquad滤波器设计

用复平面几何法直观理解Biquad滤波器设计 当你第一次接触数字滤波器时&#xff0c;那些复杂的差分方程和z变换公式是否让你望而生畏&#xff1f;作为音频处理领域的入门者&#xff0c;我曾花了整整两周时间试图理解一个简单的二阶滤波器公式&#xff0c;直到发现了复平面几何法…...

如何5步将小爱音箱改造成专属AI语音助手:MiGPT终极指南

如何5步将小爱音箱改造成专属AI语音助手&#xff1a;MiGPT终极指南 【免费下载链接】mi-gpt &#x1f3e0; 将小爱音箱接入 ChatGPT 和豆包&#xff0c;改造成你的专属语音助手。 项目地址: https://gitcode.com/GitHub_Trending/mi/mi-gpt 你是否曾想过让小爱音箱摆脱&…...

性价比高可代理的油烟分离油烟机的厂家

最近跟10多个开厨电店的老板喝茶&#xff0c;一半人唉声叹气&#xff1a;去年赚的钱全压库存里了&#xff0c;3个做了十几年的老老板说&#xff0c;再找不到好产品&#xff0c;今年打算把店转了。为啥好好的店做成这样&#xff1f;说白了就是选品选错了&#xff0c;风口变了&am…...

Linux安装配置小龙虾【openclaw】(飞牛NAS OS)

OneAPI & NewAPI 完全指南&#xff1a;从零开始搭建你的AI模型聚合网关 在AI大模型百花齐放的今天&#xff0c;我们常常需要同时使用多个模型提供商的服务——OpenAI的GPT-4、Anthropic的Claude、Google的Gemini、国内的文心一言、通义千问等等。每个提供商都有自己的API接…...

OpenSpeedy:终极免费游戏变速工具完整使用指南

OpenSpeedy&#xff1a;终极免费游戏变速工具完整使用指南 【免费下载链接】OpenSpeedy &#x1f3ae; An open-source game speed modifier. 项目地址: https://gitcode.com/gh_mirrors/op/OpenSpeedy OpenSpeedy是一款完全免费且开源的Windows游戏加速工具&#xff0c…...

GPU硬件操作强度与LLM推理效率优化实践

1. 硬件操作强度&#xff08;HOI&#xff09;与LLM推理效率的深度解析在GPU加速的大型语言模型推理场景中&#xff0c;我们常常遇到一个看似矛盾的现象&#xff1a;计算单元利用率不足的同时&#xff0c;显存带宽却成为瓶颈。这种现象的根源在于硬件操作强度&#xff08;Hardwa…...