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 7fmt.Println(array, len(array), cap(array))//查看slice1切片的信息 [4 5] 2 4fmt.Println(slice1[:], len(slice1[:]), cap(slice1[:]))//查看slice1切片依托底层数组的信息 [4 5 0 1] 4 4fmt.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创建sliceslice := 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创建sliceslice := 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.mzph.cn/bicheng/20872.shtml

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

相关文章

半导体光子电学期末笔记1: 电磁光学基本理论

Chapter 2: 电磁光学基本理论 电磁光学理论概述 真空中麦克斯韦方程组[p9] 在自由空间中,麦克斯韦方程组可以写成如下形式: { ∇ H ϵ 0 ∂ E ∂ t (1) ∇ E − μ 0 ∂ H ∂ t (2) ∇ ⋅ E 0 (3) ∇ ⋅ H 0 (4) \begin{cases} \nabla \times \…

Java——异常详解

异常五个主要关键字:throw、try、catch、finally、throws 1. 异常的概念与体系结构 1.1 异常的概念 在Java中,程序执行过程中发生的不正常行为被称为异常,如: 1. 算数异常 public static void main(String[] args) {System.ou…

基于MingGW64 GCC编译Windows平台上的 libuvc

安装cmake 打开cmake官网 https://cmake.org/download/,下载安装包: 安装时选择将cmake加到系统环境变量里。安装完成后在新的CMD命令窗口执行cmake --version可看到输出: D:\>cmake --version cmake version 3.29.3 CMake suite mainta…

牛客网刷题 | BC108 反斜线形图案

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 描述 KiKi学习了循环&am…

社交媒体数据恢复:Voxer

一、Voxer数据恢复教程 了解Voxer应用 Voxer是一款专门为iPhone和Android智能手机设计的免费对讲机应用,为用户提供即时的语音、文本、照片等信息发送和接收服务。该应用有点类似短信服务,但用声音代替文本。当你下载之后,如果不邀请朋友&a…

重复文件怎么查找并清理?电脑重复文件清理工具分享:4个

在日常使用电脑的过程中,我们不可避免地会遇到各种重复文件的问题。这些重复文件不仅占据了宝贵的存储空间,还可能导致系统性能下降,甚至引发一些不必要的问题。因此,如何有效地查找并清理这些重复文件成为了许多用户关注的焦点。…

计算 x 的二进制表示中 1 的个数

计算 x 的二进制表示中 1 的个数 代码如下: int func(int x){int countx 0;while (x>0){countx;x x & (x - 1);}return countx;} 完整代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Dat…

STM32基于HAL库的HC-SR04模块超声波测距

文章目录 一、HC-SR04模块介绍二、创建工程1.选择芯片2.配置RCC、SY![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9d2a5b883f0e409eabb804e6da861277.png)3.配置串口14.配置定时器5.配置GPIO 三、Keil代码1.勾选Use MicroLIB2.创建SR04.c和SR04.h文件3.其他代码 …

html three.js 引入.stl模型示例

1.新建一个模块用于放置模型 <div id"chart_map" style"width:800px;height:500px"></div> 2. 引入代码根据需求更改 <!-- 在head或body标签内加入以下链接 --> <script src"https://cdn.jsdelivr.net/npm/three0.137/build/t…

2.7HDR与LDR

一、基本概念 1.基本概念 动态范围&#xff08;Dynamic Range&#xff09; 最高亮度 / 最低亮度 HDR High Dynamic RangeLDR Low Dynamic Range HDR与LDR和Tonemapping的对应关系&#xff1a; 我们常用的各种显示器屏幕&#xff0c;由于不同的厂家不同的工艺导致它们的…

HALCON-从入门到入门-软件界面介绍

1.废话 从halcon12到halcon23&#xff0c;开发的IDE界面大差不差&#xff0c;简单说下界面上不同功能按键的分布&#xff0c;以及一些快捷键啥的&#xff0c;要是还有我没有总结到的&#xff0c;又比较好用的&#xff0c;欢迎大家补充一下。 1.菜单栏 从上看到下&#xff0c;…

python深度学习入门-从零构建CNN和RNN

文章目录 第1章 基本概念1.1. 导数1.2. 链式法则1.3. 多输入函数的导数1.4. 多输入向量函数的导数1.5. 向量函数及其导数&#xff1a; 再进一步1.6. 包含两个二维矩阵数据的计算图 第2章 基本原理2.1. 监督学习概述2.2. 监督学习模型2.3. 线性回归2.3.1. 线性回归&#xff1a; …

[激光原理与应用-94]:电控 - 低噪声运放的原理

目录 一、什么是低噪声运放 1.1 什么是低噪声水平 1.2 什么是高增益 在电子工程中的应用 在通信领域的应用 在音频和视频处理中的应用 注意事项 1.3 什么是宽带宽 1.4 什么是低偏置电流 重要性 特点 解决方法 应用 二、低噪声运放的原理图 1. 基本构成 2. 设计…

第五维度【百度之星】/二分

第五维度 二分 思路&#xff1a;看到题目是尽可能晚的情况下最早就应该想到贪心。 #include<bits/stdc.h> using namespace std; typedef long long ll; ll a[100005],b[100005]; ll n,m; bool check(ll t) {ll res0,big0;for(ll i0;i<n;i) {if(a[i]>t) continue…

JMeter工具介绍

Jmeter功能概要 JDK常用文件目录介绍 Bin目录&#xff1a;存放可执行文件和配置文件 Docs目录&#xff1a;是Jmeter的API文档&#xff0c;用于开发扩展组件 printable_docs目录&#xff1a;用户帮助手册 lib目录&#xff1a;存放JMeter依赖的jar包和用户扩展所依赖的Jar包 修…

HALCON-从入门到入门-读取图片保存图片

1.废话 视觉算法库的第一步。 读取图片&#xff1a; 看你是从哪里读取&#xff0c;从相机读取还是从本地硬盘中读取。 保存图片&#xff1a;就只有保存到本地了。 上面的截图显示我读取了一张图片 从相机中读取另开一篇来说&#xff0c;先说从本地磁盘读取哈。 怎么读取的…

数据结构复习指导之交换排序(冒泡排序,快速排序)

目录 交换排序 复习提示 1.冒泡排序 1.1基本思想 1.2算法代码 1.3性能分析 2.快速排序 2.1基本思想 2.2算法代码 2.3性能分析 交换排序 复习提示 所谓交换&#xff0c;是指根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。 基于交换的排序算法很…

python解决flask启动的同时启动定时任务

业务场景描述&#xff1a;在常规的开发中&#xff0c;我们开发接口服务&#xff0c;一般会将数据放在数据库、文件等第三方文件&#xff0c;启动服务后&#xff0c;服务到后台数据库中加载数据&#xff0c;这样做的好处当然是开发会更加便利以及数据的可复用性较高&#xff0c;…

深度学习-03-函数的连续调用

深度学习-03-函数的连续调用 本文是《深度学习入门2-自製框架》 的学习笔记&#xff0c;记录自己学习心得&#xff0c;以及对重点知识的理解。如果内容对你有帮助&#xff0c;请支持正版&#xff0c;去购买正版书籍&#xff0c;支持正版书籍不仅是尊重作者的辛勤劳动&#xff0…

LLaMA-Factory推理实践

运行成功的记录 平台&#xff1a;带有GPU的服务器 运行的命令 git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory/ conda create -n py310 python3.10 conda activate py310由于服务器不能直接从huggingface上下载Qwen1.5-0.5B&#xff0c;但本地可…