Go语言-切片底层探索 —— 补充篇:切片和底层数组到底是什么关系?

news2024/12/24 0:18:41

之前的切片探索中,上篇通过一道算法题目,了解到切片的两大特性:一是:切片是引用类型,指向底层数组,修改其底层数组的时候,会影响切片中的值。二是:向切片中添加元素的时候,切片可能会发生扩容,改变其底层指向的数组。在下篇中,我们谈到了切片的底层实现原理以及扩容机制。在之后的学习中,切片的应用场景比较多,自己也有了一些新的发现,于是形成补充篇这个文章。接下来我会从切片的几种创建方式说明切片和底层数组之间的关系、切片作为函数的参数时,实际上传递的是什么?
上下两篇:
1.GO语言-切片底层探索(上)-CSDN博客
2.GO语言-切片底层探索(下)-CSDN博客

1. 查看切片底层依托的数组

func main() {
	//切片slice1基于array数组创建的
	array := [7]int{1, 2, 3, 4, 5, 0, 1}
	slice1 := array[3:5]
	//查看array数组的信息 [1 2 3 4 5 0 0] 7 7
	fmt.Println(array, len(array), cap(array))
	//查看slice1切片的信息 [4 5] 2 4
	fmt.Println(slice1[:], len(slice1[:]), cap(slice1[:]))
	//查看slice1切片依托底层数组的信息 [4 5 0 1] 4 4
	fmt.Println(slice1[:cap(slice1)], len(slice1[:cap(slice1)]), cap(slice1[:cap(slice1)]))
}

 在上面的代码中,我们发现一个奇怪的现象:当我们使用切片表达式slice1[:]和slice1[:cap(slice1)]所取到的值是完全不同的。

我们常用到的切片表达式是slice[low:high]这种两个参数的形式,我们称其为简单切片表达式。此外还有一种三个参数形式的切片表达式,我们称其为扩展切片表达式,但是一般不经常使用,这里权当扩展一下。在简单切片表达式中,切片的长度length = high-low,切片的容量cap = 底层数组的长度-low。这里的low和high都是可以省略的,如果省略low则默认为0,如果省略high则默认为切片的长度,而不是容量。

slice1[:]实际上取的是切片的范围,也就是从切片的下标0到切片的长度-1。而slice1[:cap(slice1)]底层数组的范围,从slice1所依托得底层数组从下标low(这里是3,因为我们的slice1= array[3:5]),到底层数组末尾。

虽然我们在项目中一般不使用slice[:cap(slice)]这种形式,但是我们知道如果通过获取切片所依托的底层数组的方法,可以帮助我们更加清晰地理解切片和底层数组的关系,以及切片中的len和cap实际代表的是什么!

2. 切片和底层数组的关系

  1. 直接赋值方式 slice:= []int{1,2,3,4,5}
  2. make字面量方式 slice:= make([]int,0,10)
  3. 使用切片表达式根据切片或数组生成 slice:= array0[1:3]

通过之前的文章,我们知道,切片是依托于数组实现的,相比于数组而言,切片在容量不足的时候,会进行自动扩容,更具有灵活性。我们一般都是通过以上三种方式创建切片的,这三种不同的创建方式,将形成三种不同的(切片和其底层数组之间的)关系。

  1. 直接赋值创建方式,这种方式创建出来的切片长度等于容量,此时如果我们向切片中添加一个新的元素,就会触发扩容机制,改变切片指向的底层数组。
  2.  make字面量方式 slice:= make([]int,0,10),通过make创建切片,可以指定切片的长度和容量(底层数组的长度),后续向切片中添加元素的个数,如果没有超过10就不会发生扩容。通过提前指定切片的容量,可以减少程序运行过程中,切片扩容带来的资源消耗。
  3. 使用切片表达式根据切片或数组生成 slice:= array0[low:high]。使用切片表达式创建的切片,其长度为high-low,容量是底层数组的长度-low。

3. 切片作为函数的参数时,传递的是对底层数组的引用

func main() {
	baseArray := [5]int{1, 2, 3, 4, 5}
	//基于baseArray创建slice
	slice := baseArray[:] 
	modifySlice(slice, 0)
	fmt.Println(slice, len(slice), cap(slice))             // 输出 [100 2 3 4 5]
	fmt.Println(baseArray, len(baseArray), cap(baseArray)) // 输出 [100 2 3 4 5]
}

func modifySlice(slice []int, index int) {
	slice[index] = 100
}

在代码中,我们基于baseArray创建slice,我们发现当传入的切片在函数中修改时,其依赖的底层数组也发生了修改。这说明,切片作为函数的参数时,实际上传递是对底层数组的引用。如果我们在函数的操作导致切片进行了扩容,那么我们的底层数组中的值将不会再发生变化了。

测试如下:

func main() {
	baseArray := [5]int{1, 2, 3, 4, 5}
	//基于baseArray创建slice
	slice := baseArray[:]
	modifySlice(slice, 0)
	fmt.Println(slice, len(slice), cap(slice))             // 输出 [100 2 3 4 5]
	fmt.Println(baseArray, len(baseArray), cap(baseArray)) // 输出 [100 2 3 4 5]
}

func modifySlice(slice []int, index int) {
	slice[index] = 100       //baseArray[index]被修改
	slice = append(slice, 1) //扩容,底层数组改变
	slice[index] = 1000      //baseArray[index]值不变
	fmt.Println(slice, len(slice), cap(slice)) //[1000 2 3 4 5 1] 6 10
}

4. 总结

在这篇博客中,我们主要讲解切片和底层数组之间的关系,并且通过切片的三种创建方式来进行详细的说明。我们在使用切片的时候,一定要注意切片扩容后,其底层指向的数组会发生变化,对切片的修改将不再作用与原来的底层数组。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1793769.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ES6真题合集(一)

ES6真题合集(一) 1. var、let、const之间的区别2. ES6中数组新增了哪些扩展2.1 扩展运算符2.2 Array.from() 方法2.3 Array.of() 方法2.4 find() 和 findIndex() 方法2.5 箭头函数2.6 模板字符串 3. ES6中对象新增了哪些扩展3.1 属性的简写3.2 属性名表达…

[SQL-SERVER:数据库安全及维护]:MSSM工具对用户进行用户授权和角色授权操作

文章目录 直接为用户授权(20分)1. 创建登录TLogin,自行指定登录密码服务器层面选择 安全性 > 点击 登录名 > 点击右键 > 点击 新建登录名 > 选择sqlserver验证 > 关闭强制登录更改密码异常解决:sqlserver 配置管理…

Docker+JMeter+InfluxDB+Grafana 搭建性 能监控平台

JMeter原生报告的缺点: 无法实时共享 报告信息的展示不美观 需求方案 为了解决上述问题,可以通过 InfluxDB Grafana解决 : InfluxDB :是一个开源分布式指标数据库,使用 Go 语言编写,无需外部依赖 应用&am…

【C++】类和对象——构造和析构函数

目录 前言类的六个默认构造函数构造函数1.构造函数的概念2.构造函数的特性 初始化列表1.构造函数整体赋值2.初始化列表 析构函数1.析构函数的概念2.析构函数的特性 前言 类和对象相关博客:【C】类和对象   我们前面一个内容已经讲了关于类好对象的初步的一些知识&…

Linux——nginx部署

部署Nginx 构建Nginx服务器 (实验需要DNS支持,或添加hosts条目,例如: ) 安装Nginx(yum安装即可) 安装依赖软件包: 重启、启用服务并查看服务状态: 默认页面&#xff0…

AIGC会带来失业潮吗?紧紧跟时代第一步,如何学习AIGC

会,但AI淘汰的始终是跟不上时代的人。 现在很多公司都有AI培训,不仅GPT,还有Midjourney、Stable DIffusion等一系列AI工具。 像我们公司虽然今年招的少,但也会对新招的应届生统一进行AI培训。 用任正非先生的话来说就是&#x…

ubuntu top命令的参数和快捷键

命令选项 -1 单个、所有cpu信息切换 top -1-b 批处理 top -b > top.txt这将保存top命令的输出到文件,直到手动终止或关机。所以使用这个命令要注意和其他命令配合,否则文件速度增长会很快。 在文件中,将会重复输入top命令。 -c 切换命…

干货!以医疗行业为例,讲解数据安全级别划分以及归纳敏感数据的处理策略

数据分类分级是一项基础工作,也是提供数据分级保护的基础措施之一,是企业长期的一项技术、管理措施。企业通过制定数据分类分级策略、模板、管理规范能够有助于帮助企业梳理清楚企业数据资产,在面向合规监管、内部数据安全控制时能够提供更完…

pyspark中使用mysql jdbc报错java.lang.ClassNotFoundException: com.mysql.jdbc.Driver解决

报错信息: py4j.protocol.Py4JJavaError: An error occurred while calling o33.load. : java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 我的解决方法: 这个报错就是提示你找不到jar包,所以你需要去下载一个和你mysql版本匹配的j…

摸鱼大数据——Hive调优16-19

16、JVM 重用 此操作, 在hive2.x已经不需要配置了, 默认支持 jvm重用: 默认情况下, container资源容器 只能使用一次,不能重复使用, 开启JVM重用, 运行container容器可以被重复使用,在hive2.x已经默认支持了 17、推测执行 调优举例: 大数据小组,假设…

Android14 WMS-窗口绘制之relayoutWindow流程(二)-Server端

本文接着如下文章往下讲 Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端-CSDN博客 然后就到了Server端WMS的核心实现方法relayoutWindow里 WindowManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server…

QT系列教程(9) 主窗口学习

简介 任何界面应用都有一个主窗口,今天我们谈谈主窗口相关知识。一个主窗口包括菜单栏,工具栏,状态栏,以及中心区域等部分。我们先从菜单栏说起 菜单栏 我们创建一个主窗口应用程序, 在ui文件里的菜单栏里有“在这里输入”的一个…

四、Window整理右键扩展

一、桌面右键和文件右键扩展整理 简而言之整理下面图示内容 桌面右键: 对文件右键: 工具:火狐自带工具 二、新建扩展管理 简而言之整理下面图示内容 Win R输入regedit 寻找:计算机\HKEY_CURRENT_USER\Software\Microsof…

中科数安 | 透明加密防泄密系统!如何有效防止企业内部核心数据资料外泄?

中科数安提供的透明加密防泄密系统是一种专为企业设计的数据保护解决方案,它通过以下关键特性有效防止企业内部核心数据资料外泄: PC地址:——www.weaem.com 自动智能透明加密:系统能够在操作系统级别无缝集成,对指定类…

重生之 SpringBoot3 入门保姆级学习(15、内容协商返回不同数据类型)

重生之 SpringBoot3 入门保姆级学习&#xff08;15、内容协商返回不同数据类型&#xff09; 3.3.3 改变 Accept 实现内容协商3.3.4 改变 application.proerties 实现内容协商 3.3.3 改变 Accept 实现内容协商 添加支持写出 xml 内容的 Maven 依赖并刷新 Maven <!-- …

日语里「ずつ」和「づつ」有什么不同,柯桥成人日语培训

在生活中&#xff0c;我们常用「1人ずつ」「一歩ずつ」表示固定数量的重复出现&#xff0c;但有时候也会写作「1人づつ」「一歩づつ」&#xff0c;究竟哪种写法才是正确的呢&#xff1f;今天这篇文章将对「ずつ」和「づつ」的正确用法进行说明。 01 使用情况 根据日本文部科学…

RLHF(从人类反馈中进行强化学习)详解(三)

在经过了前两节的内容学习之后&#xff0c;我们对于RLHF&#xff08;从人类反馈中进行强化学习&#xff09;有了比较深入的认知&#xff0c;并且初步了解了RLHF中偏好数据集的引入&#xff0c;奖励模型的设置以及baseLLM的训练过程。在本节的学习中&#xff0c;我们将深入LLM的…

Visual Studio Installer 点击闪退

Visual Studio Installer 点击闪退问题 1. 问题描述2. 错误类型3. 解决方法4. 结果5. 说明6. 参考 1. 问题描述 重装了系统后&#xff08;系统版本&#xff1a;如下图所示&#xff09;&#xff0c;我从官方网站&#xff08;https://visualstudio.microsoft.com/ ) 下载了安装程…

如何把几个pdf文件合成在一个pdf文件

PDF合并&#xff0c;作为一种常见的文件处理方式&#xff0c;无论是在学术研究、工作汇报还是日常生活中&#xff0c;都有着广泛的应用。本文将详细介绍PDF合并的多种方法&#xff0c;帮助读者轻松掌握这一技能。 打开 “轻云处理pdf官网” 的网站&#xff0c;然后上传pdf。 pd…

入门Consul注册、配置中心(代码演示)

1、安装与使用 2、注册服务到consul 3、调用consul上注册的服务 4、配置中心 1、安装与使用 官网地址&#xff1a;Install | Consul | HashiCorp Developer 下载对应的系统 解压缩后文件 打开命令行运行 consul.exe agent -dev 即可运行 可以编写一个bat脚本每次运行ba…