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 作者给出了几种原始容量下对应的“扩容系数”:
| 原始容量 | 扩容系数 |
|---|---|
| 256 | 2.0 |
| 512 | 1.63 |
| 1024 | 1.44 |
| 2048 | 1.35 |
| 4096 | 1.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]字面…...
哪个牌子充电宝好用?精选四大热门款充电宝品牌!公认好用
在当今快节奏的生活中,充电宝已经成为了我们日常生活中不可或缺的数码伴侣。无论是旅行、出差还是日常通勤,拥有一款好用的充电宝,能够确保我们的手机、平板等设备随时保持充足电量。然而,市场上充电宝品牌繁多,如何选…...
WPF/C#:如何将数据分组显示
WPF Samples中的示例 在WPF Samples中有一个关于Grouping的Demo。 该Demo结构如下: MainWindow.xaml如下: <Window x:Class"Grouping.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x&q…...
leetcode 200 岛屿数量
思路 就是深搜,将可以走到的都标为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万基础电子地图(四川版)》和《1:25基础电子地图(云南版)》等文中,为你分享过四川和云南的基础电子地图。 现在我们再为你分享江西的1:25万基础电子地图,你可以在文…...
【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自定义树状导航控件
大部分的软件都有多个页面,这时候就需要一个导航栏控件,通过在导航栏中选择某一栏,同时显示对应的页面。 本文代码效果如下: 本文的导航栏控件基于大佬 feiyangqingyun 的导航栏控件博客Qt/C编写自定义控件46-树状导航栏_qt之实现…...
Java 数组的全面解析与应用
Java 中的数组是一种基础且重要的数据结构,用于存储相同类型的多个数据项。它提供了有效的数据组织和访问机制,是 Java 编程中不可或缺的部分。本文将从多个角度全面探讨 Java 数组的特性、操作和实际应用,帮助读者深入理解和有效利用这一数据…...
Thinkphp起名网宝宝起名网站源码
Thinkphp起名网宝宝起名网站源码 源码介绍 1.宝宝在线起名 2.八字起名,周易取名 3.一对一起名 5.支持手机wap 链接数据库地址:Application\Common\Conf 修改里面config.php数据库连接,导入sm.sql数据库文件即可 伪静态用thinkphp 后台…...
【解决方案】【最佳实践】React高阶组件中Refs 不会被传递的问题
大家好,我是DX3906。 最近遇到React高阶组件中Refs 不会被传递的问题。 在这里总结一下解决方案和解决思路:主要是通过从内向外和从外向内2种思路来分析解决的。 目录 前言 解决方案一:React.forwardRef 解决方案二:使用prop…...
SRAM和DRAM
1.SRAM(静态RAM) 把存放一个二进制位的物理器件称为存储元,它是存储器最基本的构件。 地址码相同的多个存储元构成一个存储单元。 存储单元的集合构成存储体。 静态RAM的存储元是用双稳态触发器(六晶体管MOS)来记忆…...
浅析Spring中Async注解底层异步线程池原理
一、前言 开发中我们经常会用到异步方法调用,具体到代码层面,异步方法调用的实现方式有很多种,比如最原始的通过实现Runnable接口或者继承Thread类创建异步线程,然后启动异步线程;再如,可以直接用java.uti…...
sqli-labs 靶场 less-7 第七关详解:OUTFILE注入与配置
SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它,我们可以学习如何识别和利用不同类型的SQL注入漏洞,并了解如何修复和防范这些漏洞。Less 7 SQLI DUMB SERIES-7判断注入点 进入页面中,并输入数据查看结果。 发现空数据提…...
AIGC新秀亮相,哪款大模型产品最得你心?
AIGC新秀亮相,哪款大模型产品最得你心? 近日,腾讯元宝APP的正式上线,为国内大模型AIGC产品市场增添了一名新成员。 这些所谓的“全能”大模型产品,凭借其强大的生成能力和广泛的应用场景,正逐渐改变我们的…...
RabbitMQ消息的可靠传输和防止消息丢失
在Spring Cloud项目中,为了确保RabbitMQ消息的可靠传输和防止消息丢失,需要考虑以下几个方面: 消息持久化:确保消息在RabbitMQ中持久化。队列持久化:确保队列是持久化的。发布确认:使用发布确认机制确保消…...
.net8系列-图文并茂手把手教你使用Nlog记录.net日志
Nlog是什么? NLog是一个为.NET平台设计的灵活且免费的日志记录库。它适用于包括.NET Framework、.NET Core和.NET Standard在内的多种.NET环境。 Nlog有什么好处或者特点? 配置灵活:NLog允许开发者通过配置文件(通常是NLog.conf…...
课时158:脚本发布_简单脚本_远程执行
2.1.3 远程执行 学习目标 这一节,我们从 基础知识、简单实践、小结 三个方面来学习 基础知识 简介 有时候,我们需要通过远程方式到另外一台主机进行脚本的执行 格式:ssh 远程主机登录用户名远程主机ip地址 "执行命令"效果 [r…...
3dmax2025能用云渲染吗?2025最新云渲染渲染100使用方法
3dmax2025还没用上云渲染?简单3步用上云渲染。 第一步,打开浏览器搜索渲染100,并进入下载客户端并安装 第二步,打开已安装的客户端进行安装,点击登录,未登录注册个账号即可(注册账号时邀请码填…...
从零开始学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. 判别分析简介 判别分析(Discriminant Analysis) 是一种统计方法,用于在已知分类的样本中构建分类器,并根据特征变量对未知类别的样本进行分类。常见的判别分析方法包括线性判别分析(Linear Discriminant Analysis, …...
全格式文档智能处理:AnythingLLM的多模态知识管理解决方案
全格式文档智能处理:AnythingLLM的多模态知识管理解决方案 【免费下载链接】anything-llm 这是一个全栈应用程序,可以将任何文档、资源(如网址链接、音频、视频)或内容片段转换为上下文,以便任何大语言模型(…...
2026年必看:专业婚恋软件推荐,找到真爱不迷路
在当今快节奏的社会中,越来越多的高知青年面临着交友难、脱单难的问题。传统的社交方式往往难以满足他们对高质量伴侣的需求,而专业的婚恋软件则成为他们寻找真爱的重要途径。本文将重点推荐一款备受好评的婚恋软件——即恋App,并结合具体数据…...
开源项目国际化:多语言配置全流程指南
开源项目国际化:多语言配置全流程指南 【免费下载链接】pivottable Open-source Javascript Pivot Table (aka Pivot Grid, Pivot Chart, Cross-Tab) implementation with dragndrop. 项目地址: https://gitcode.com/gh_mirrors/pi/pivottable 跨国团队如何让…...
Debian12下Docker国内镜像加速全攻略:以腾讯云为例快速部署WordPress
Debian12下Docker国内镜像加速全攻略:以腾讯云为例快速部署WordPress 在Debian12系统中使用Docker时,国内用户常遇到镜像下载速度慢的问题。本文将详细介绍如何配置国内镜像源加速Docker,并以腾讯云为例,快速部署WordPress环境。…...
Obsidian Local Images Plus 终极指南:如何一键解决所有本地图片管理难题
Obsidian Local Images Plus 终极指南:如何一键解决所有本地图片管理难题 【免费下载链接】obsidian-local-images-plus This repo is a reincarnation of obsidian-local-images plugin which main aim was downloading images in md notes to local storage. 项…...
OpenClaw自动化测试框架:百川2-13B驱动的CI/CD辅助方案
OpenClaw自动化测试框架:百川2-13B驱动的CI/CD辅助方案 1. 为什么选择OpenClaw做测试自动化 去年我在重构一个中型前端项目时,遇到了测试覆盖率不足的老问题。手动补测试用例不仅耗时,还经常遗漏边界条件。当我尝试用传统测试生成工具时&am…...
5分钟搞定PaddleOCR文字识别:Python版保姆级教程(附完整代码)
5分钟极速上手PaddleOCR:Python实战指南与避坑手册 第一次接触OCR技术时,我被那些复杂的配置参数和晦涩的文档吓退了三次。直到发现PaddleOCR这个"开箱即用"的工具,才明白原来文字识别可以如此简单。本文将带你用最直接的方式&…...
iText7中文渲染完全指南:从乱码到完美显示的技术突破
iText7中文渲染完全指南:从乱码到完美显示的技术突破 【免费下载链接】itext7-chinese-font 项目地址: https://gitcode.com/gh_mirrors/it/itext7-chinese-font 在数字化文档处理领域,PDF格式以其跨平台一致性成为信息传递的首选。然而…...
基于pso-LSTM的锂电池SOH健康状态预测模型(NASA数据集)B0005、B0006、B...
基于pso-LSTM的锂电池SOH健康状态预测模型(NASA数据集)B0005、B0006、B0007、B0008四个电池数据集。 在数据预处理阶段,用户可以自行完成SOH(State of Health)的计算,然后通过pso-LSTM神经网络进行预测。 该…...
Spring PetClinic实战解析:从单体应用到云原生部署的5大架构亮点
Spring PetClinic实战解析:从单体应用到云原生部署的5大架构亮点 【免费下载链接】spring-petclinic A sample Spring-based application 项目地址: https://gitcode.com/gh_mirrors/sp/spring-petclinic 你是否遇到过这样的困境:在学习Spring框架…...
