当前位置: 首页 > 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, …...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...