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

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...