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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

限流算法整理——滑动窗口限流算法

限流算法描述 滑动窗口限流需要将每个窗口空间划分为无限小的窗口区间,并且动态调整区间的起始点,并且在调整完毕之后需要判断各个区间,累加各个区间的请求,查看是否到达最大的阈值,以此返回允许请求还是拒绝请求 算…

SDL教程(二)——Qt+SDL播放器

前言 ​ 这篇文章主要是使用SDL来打开视频,显示视频。后续会再继续使用SDL来结合FFmpeg。来能够直接使用网上的demo进行学习。 正文 一、环境 Qt 5.15.2 MSVC2019 64bit Win11 二、Qt搭建SDL Qt搭建,我觉得相比用VS2019来说,更为方便&…

密文域可逆信息隐藏安全性研究-从图像到视频

前言 随着云存储、云计算等新兴技术的兴起,海量的隐私信息被广泛地上传、存储到服务器上。为保证用户的隐私性,必须对用户的数据进行加密,然后再将其上传到服务器上。因此,密文域的可逆信息隐藏(reversible data hiding in encry…

Vue3 -Computed计算属性

前言: Computed属性属于Vue3中的响应式核心(与之共同说明的还有ref,reactive,watch...) 接受一个 getter 函数,返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。它也可以接受一个带有 get 和 set…

内网-1(win工作组与域环境)

一、概述 1、工作组:将不同的计算机按功能(或部门)分别列入不同的工作组 (1)、查看(windows) 查看当前系统中所有用户组:打开命令行--》net localgroup查看组中用户:打开命令行 --》net localgroup 后接组名查看用户…

【C语言进阶】文件操作:文件的打开与文件的读写以及文本文件和二进制文件

目录 1、为什么使用文件 2、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3、文件的打开和关闭 3.1文件指针 3.2文件的打开与关闭 4、文件的顺序读写 4.1 几个函数的区别 5、文件随机读写 5.1 fseek 5.2 ftell 5.3 rewind 6、文本文件和二进制文件…

APM32F003评测,基本参数,点LED

简介 该是一个基于APM32F003 32位Cortex-M0 工业级 单片机开发板。主频高达48MHz,AHB 总线、APB 总线,无需外部晶振即可运行,价格实惠。为专业人士、工业ODM、AIoT爱好者、DIY爱好者和创作者提供了一个可靠、低成本和高性能的平台。 这款开发…

LangChain学习圣经:从0到1精通LLM大模型应用开发的基础框架

尼恩:LLM大模型学习圣经PDF的起源 在40岁老架构师 尼恩的读者交流群(50)中,经常性的指导小伙伴们改造简历。 经过尼恩的改造之后,很多小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试机会&#x…

MFC3d立体按钮制作

1、本程序基于前期我的博客文章MFC用CButtonST类实现图片透明按钮(免费源码下载) 2、添加CeXDib.cpp CeXDib.h ShadeButtonST.cpp ShadeButtonST.h到项目文件夹下,和FileView中如图。 3、在ButtonShadeDlg.h中添加代码 #include "ShadeButtonST.h" #in…

回文串算法题

回文串是一个正着读和反着读顺序一样的字符串。"aba" 是回文串,"abba" 是回文串,"abc" 不是回文串。 回文串的题目,都要使用一个基本的逻辑,就是判断当前这个字符串是不是回文串。以 c 为例&#…

无限光年人工智能技术创新PMO负责人端煜受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 无限光年(上海)技术有限公司人工智能技术创新PMO负责人、原字节跳动朝夕光年PMO总监端煜先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾,演讲议题为“中国传统哲学在LLM企业项目管理应用中的思考与实践”。…

移植2D物理引擎到LVGL

背景 在LVGL交流群,有网友提出想要移植物理引擎到LVGL,遂有了本文。阅读本文需要对IDF和LVGL有所了解 过程 2D物理引擎有很多,经过一番调研选择了Chipmunk2D 下载源码 此处省略一万字,Github访问可能会有些慢 添加文件 将…

达梦8 内存泄漏泄漏原因分析之一

在实际使用过程中经常发现DMSERVER进程在OS中的内存占用使用远远超过实际情况。原因有很多,下面列出其中一种: 测试库版本 SQL> select id_code;LINEID ID_CODE ---------- ----------------------------------- 1 --03134283938-2022…

DPDK基础组件一(mbuf、ring、pktmbuf_pool)

一、rte_mbuf 此部分转自:https://zhuanlan.zhihu.com/p/616314276 1.mbuf结构 mbuf是报文中的描素的结构体,是整个转发过程中最核心的数据结构之一。主要针对于mbuf的常用API与基本原理做一个简单的介绍。 mbuf:报文内存存储结构,存储在mempool中mempool:使用环形缓冲…

如何选择D类音频放大器(数字功率放大器)

1 简介 多年来,音频内容一直在不断发展。从当地唱片店购买 12 英寸 LP 黑胶唱片的时代已经成为过去,现在我们通过流式传输几乎可即时播放云端的任何内容。虽然一些音频爱好者会为了获得新奇体验而重拾黑胶唱片,但今天绝大多数的音频都是以数…

基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细

基于Nginx和Consul构建自动发现的Docker服务架构 文章目录 基于Nginx和Consul构建自动发现的Docker服务架构资源列表基础环境一、安装Docker1.1、Consul节点安装1.2、registrator节点安装 二、案例前知识点2.1、什么是Consul 三、基于Nginx和Consul构建自动发现的Docker服务架构…

[NOIP2015 提高组] 子串

题目背景 NOIP2015 Day2T2 题目描述 有两个仅包含小写英文字母的字符串 A A A 和 B B B。 现在要从字符串 A A A 中取出 k k k 个互不重叠的非空子串,然后把这 k k k 个子串按照其在字符串 A A A 中出现的顺序依次连接起来得到一个新的字符串。请问有多少…

从集合论到位运算

前言 本文将扫清位运算的迷雾,在集合论与位运算之间建立一座桥梁。 在高中,我们学了集合论(set theory)的相关知识。例如,包含若干整数的集合 S{0,2,3}。在编程中,通常用哈希表(hash table&…

计算机网络学习2

文章目录 信道复用技术 第三章数据链路层概述数据链路层的三个重要问题封装成帧和透明传输差错检测可靠传输的相关基本概念可靠传输的实现机制停止等待协议回退N帧协议选择重传协议 点对点协议PPP共享式以太网网络适配器和MAC地址CSMA_CD协议的基本原理共享式以太网的争用期共享…

【计算机毕业设计】331基于微信小程序的家庭财务管理系统

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…