GO语言-切片底层探索(下)
目录
切片的底层数据结构
扩容机制
总结:
练习验证代码
这是切片的底层探索下篇,上篇地址请见:GO语言-切片底层探索(上)
在上篇我们讲解了切片的两个重要实现或者说是两个特征
- 切片是引用类型,会进行引用传递;
- 切片会随着元素数量的增加,进行扩容,改变其底层数组的指向;
这篇文章我们将会顺着讲解切片的底层数据结构和扩容机制
切片的底层数据结构
我们可以在src/runtime/slice.go下看到切片slice的底层数据结构:
type slice struct {array unsafe.Pointerlen intcap int
}
我们可以发现,切片slice的基础定义很简单:
- 指针类型的array,指向底层数组
- int类型的len,存储切片的长度
- int类型的cap,存储切片的容量
由于在slice结构体中直接定义了len、cap字段,因此我们平常使用len(slice)和cap(slice),其时间复杂度为O(1),不需要遍历整个切片。
扩容机制
Go语言切片的扩容机制由基本机制和调整机制组成
func growslice(oldPtr unsafe.Pointer, newLen, oldCap, num int, et *_type) slice {.....newcap := oldCapdoublecap := newcap + newcapif newLen > doublecap {newcap = newLen} else {const threshold = 256if oldCap < threshold {newcap = doublecap} else {// Check 0 < newcap to detect overflow// and prevent an infinite loop.for 0 < newcap && newcap < newLen {// Transition from growing 2x for small slices// to growing 1.25x for large slices. This formula// gives a smooth-ish transition between the two.newcap += (newcap + 3*threshold) / 4}// Set newcap to the requested cap when// the newcap calculation overflowed.if newcap <= 0 {newcap = newLen}}}......
}
基本机制:
- 如果新切片的长度大于旧切片的二倍容量,就直接令新切片的容量等于新切片的长度
- 如果旧切片的容量小于256,进行二倍扩容
- 如果就切片的容量大于等于256,按照newcap+=(newcap+3*threshold)/4公式进行扩容,扩容速度减缓,向1.25倍进行过渡。
在基本扩容规则的基础上,还会考虑元素类型与内存分配规则,对实际的扩张值做一些微调。从这一个基本规则中我们可以看出Go语言对slice性能和空间使用率的思考:
- 当切片较小时,采用较大的扩容倍速,可以避免频繁地扩容,从而减少内容分配次数和数据拷贝的代价。
- 当切片较大时,采用较小的扩容倍速,主要是为了避免空间浪费。
因此,使用append()向slice添加一个元素的实现步骤如下:
- 假如slice容量够用,则将新元素追加进去,slice.len++,返回原slice
- 原slice容量不够,则将slice先扩容,扩容后得到新slice
- 将新元素追加进新slice,slice.len++,返回新的slice。
总结:
切片是go语言中常用的容器,由于其扩容特性,容易发生一些不容易被发现的错误,这就需要我们对切片的底层扩容机制有足够的了解,知道什么时候切片会进行扩容操作和如果高效地使用切片进行数据的存储和处理。
练习验证代码
package mainimport "fmt"type student struct {name stringage intaddress string
}func main() {//256以下的二倍扩容slice := make([]int, 255)fmt.Println(len(slice), cap(slice))newSlice := append(slice, 2)fmt.Println(len(newSlice), cap(newSlice))
}/*func main() {//结构体指针类型切片cap为1024的1.5倍扩容array := make([]*student, 1024)fmt.Println(len(array), cap(array))slice := arrayslice = append(slice, &student{name: "wang", age: 12, address: "河南"})fmt.Println(len(slice), cap(slice))
}*//*func main() {//结构体类型切片cap为1024的1.6倍扩容array := make([]student, 1024)fmt.Println(len(array), cap(array))slice := arrayslice = append(slice, student{name: "wang", age: 12, address: "河南"})fmt.Println(len(slice), cap(slice))
}*///func main() {
// //int类型的cap为1024的1.5倍扩容
// array := make([]int, 1024)
// fmt.Println(len(array), cap(array))
// slice := array
// slice = append(slice, 1)
// fmt.Println(len(slice), cap(slice))
//}
相关文章:
GO语言-切片底层探索(下)
目录 切片的底层数据结构 扩容机制 总结: 练习验证代码 这是切片的底层探索下篇,上篇地址请见:GO语言-切片底层探索(上) 在上篇我们讲解了切片的两个重要实现或者说是两个特征 切片是引用类型,会进行…...
物理隔离条件下,如何安全高效地进行内外网文件导入导出?
内外网文件导入导出通常指的是在内部网络(内网)和外部网络(外网)之间传输文件的过程。这在企业环境中尤其常见,因为内部网络通常包含敏感数据,而外部网络(如互联网)则允许更广泛的访…...
代码随想录 贪心算法-难度题目-区间问题
目录 55.跳跃游戏 45.跳跃游戏|| 452.用最少数量的箭引爆气球 435.无重叠区间 763.划分字母区间 56.合并区间 55.跳跃游戏 55. 跳跃游戏 中等 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大…...
地理数据 vs. 3D数据
在表示我们周围的物理世界时,地理空间数据和 3D 建筑数据是两个最常见的选择。 他们在各个行业和项目中发挥着至关重要的作用。 从构建数字孪生到可视化城市景观和创建沉浸式应用程序。 尽管地理空间和 3D 建筑数据有相似之处,但它们不可互换。 虽然地…...
Redis删除
一、del命令 del命令是Redis提供的一个常规的删除键的命令。它的语法如下: DEL key [key …] 其中,key是要删除的键名。可以指定多个键名,删除多个键。如果指定的键不存在,则会被忽略。 del命令会直接删除指定的键以及与之相关联…...
力扣细节题:字符串中的最大奇数
奇数只要找到第一位是奇数的即可,不是找单个数字 //即从最低位开始,找到第一位为奇数的位 //然后之前的就是需要的数字char * largestOddNumber(char * num){int i strlen(num) - 1;while(i > 0){if((num[i] - 0) % 2 1)break;i--;}//先找到低位开…...
Unity PS5开发 天坑篇 之 申请开发者与硬件部署01
腾了好几天终于把PS5开发机调试部署成功, 希望能帮到国内的开发者, 主机游戏PlayStation/Nintendo Switch都是比较闭塞的,开发者账号是必须的。 开发环境有两个部分,一是DEV Kit 开发机, TEST Kit测试机两部分组成,二是Unity的支持库(安装后…...
十四届蓝桥杯省赛Java B组 合并区域
就是将两个矩阵进行拼接,两矩阵可以旋转90 180 270 度。 因为数据比较小,所以这基本上就是一个大的枚举模拟加搜索,直接暴力求解。 import java.io.*; import java.util.*;public class Main{static int n;static int N 101;static int mo…...
SpringBoot高级
1.自动配置-Condition Condition是Spring4.0后引入的条件化配置接口,通过实现Condition接口可以完成有条件的加载相应的Bean 进入 SpringBoot 启动类,点击进入 run() 可以看到这个方法是有返回值的,返回值为 ConfigurableApplicationConte…...
机试:偶数分解
题目描述: 代码示例: #include <bits/stdc.h> using namespace std; int main(){ // 算法思想1:遍历小于该偶数的所有素数,存入数组中,遍历数组找出两个数之和等于偶数的数int n;cout << "输入样例" << endl;cin >> n;int nums[n];int k …...
一周学会Django5 Python Web开发-Jinja3模版引擎-安装与配置
锋哥原创的Python Web开发 Django5视频教程: 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计35条视频,包括:2024版 Django5 Python we…...
python前端开发
前端开发 快速网站开发 from flask import Flask appFlask(__name__) #创建网址/show/info 和函数index的对应关系, #访问网站,执行index()函数 app.route("/show/info") def index():return "中国联通" if __name__"__main_…...
web学习笔记(三十三)
目录 1.严格模式 1.1严格模式的概念: 1.2严格模式在语义上更改的地方: 1.3如何开启严格模式 1.4严格模式应用上的变化 2.原型链 1.严格模式 1.1严格模式的概念: 严格模式有点像es5向es6过渡而产生的一种模式,因为es6的语法…...
flask库
文章目录 flask库1. 基本使用2. 路由路径和路由参数3. 请求跳转和请求参数4. 模板渲染1. 模板变量2. 过滤器3. 测试器 5. 钩子函数与响应对象 flask库 flask是python编写的轻量级框架,提供Werkzeug(WSGI工具集)和jinjia2(渲染模板…...
专业无网设备如何远程运维?向日葵远程控制能源场景案例解析
清洁能源领域,拥有庞大的上下游产业链,涉及的相关工业设备门类多、技术覆盖全、行业应用广。在这一领域内,相关专业设备的供应商的核心竞争力除了本身产品的技术能力之外,服务也是重要的一环。 某企业作为致力于节能环保方向的气…...
基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的稻田虫害检测系统详解(深度学习+Python代码+UI界面+训练数据集)
摘要:本篇文章深入探讨了如何利用深度学习技术开发一个用于检测稻田虫害的系统,并且分享了完整的实现过程和资源代码下载。该系统采用了当前的YOLOv8、YOLOv7、YOLOv6、YOLOv5算法,对其进行了性能对比,包括mAP、F1 Score等关键指标…...
实现upt下客户端用tftp文件传输协议编写客户端发送下载文件
#include <myhead.h> #define SEP_IP #define SEP_PORT int main(int argc, const char *argv[]) {//创建套接字if(int crdsocket(AF_INET,SOCK-DGRAM)-1);{perror("socket error");return -1;}printf("创建成功\n");//填充地址struct sockaddr_in s…...
什么软件可以改ip地址
修改ip地址的软件有哪些,什么软件可以切换电脑手机的ip地址想必很多朋友都在寻找类似的软件,也想知道其中的答案,也能提高自己工作的效率。 经过小编在互联网摸爬滚打这些年,测试认证和整理后,发现一款名叫深度IP转换…...
C#,文字排版的折行问题(Word-wrap problem)的算法与源代码
1、英文的折行问题 给定一个单词序列,以及一行中可以输入的字符数限制(线宽)。 在给定的顺序中放置换行符,以便打印整齐。 假设每个单词的长度小于线宽。 像MS word这样的文字处理程序负责放置换行符。 这个想法是要有平衡的线条。…...
VUE+VScode+elementUI开发环境
0.vue官方文档 你正在阅读的是 Vue 3 的文档! 1.前端准备阶段 VUEVScodeelementUI开发环境 2.Vue外部组件 element-ui 3.angular外部组件 angular-ui 4.教学视频 尚学堂b站视频 5.教学视频配套文档 D:\BaiduNetdiskDownload\025【尚学堂】全新2022版WEB前端为初学者…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
