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.rhkb.cn/news/342244.html

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

相关文章

面试(03)————多线程

目录 一、线程和进程的区别? 二、并行和并发的区别? 三、线程创建的方式有哪些? 3.1、继承Thread类 3.2、实现Runnable接口 3.3、实现Callable接口 3.4、线程池 四、Runnable和Callable的区别? 五、在启动线程的时候&am…

Rocky Linux安装与基础配置

目录 背景与起源 主要特点 目标用户 发展前景 下载 安装 常用配置命令: 更换镜像源 Rocky Linux 是一个开源的、由社区驱动的操作系统,旨在使用 Red Hat Enterprise Linux(RHEL)源码构建的下游二进制兼容发行版。以下是关于…

Ubuntu22.04之解决:terminal使用alt+1/alt+2/alt+3失效问题(二百三十八)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

2024050401-重学 Java 设计模式《实战代理模式》

重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」 一、前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不到前进…

趣测小程序开发搭建,趣测趣玩小程序是何物?

一、趣测小程序简介 趣测趣玩小程序是一款提供趣味测试和玩乐功能的应用程序。用户可以通过该小程序参与各种有趣的测试,这些测试可能涵盖性格、情感、智力等多个方面,旨在为用户提供轻松愉快的体验。同时,该小程序还可能包含一些游戏元素&a…

Spring boot 随笔 1 DatasourceInitializer

0. 为啥感觉升级了 win11 之后,电脑像是刚买回来的,很快 这篇加餐完全是一个意外:时隔两年半,再看 Springboot-quartz-starter 集成实现的时候,不知道为啥我的h2 在应用启动的时候,不能自动创建quartz相关…

Vue3项目炫酷实战,检测密码强度值

在前端项目开发中,确保用户密码的强度是保护账户安全的重要措施。本文将演示如何使用Vue 3实现一个简单的密码强度检测功能。通过实时反馈,帮助用户创建更安全的密码,从而提升整体系统的安全性。无论您是前端开发新手还是经验丰富的开发者&am…

Vue2指令

本节目标 掌握vue指令 定义常用指令案例-小黑记事本指令修饰符 介绍 指令就是带有v-前缀的标签属性, 不同的指令, 可以实现不同的功能 常用指令 渲染指令 语法: v-html 动态渲染标签作用: 动态设置元素的innerHTML场景: 用来动态解析标签 语法: v-text 动态渲染文本会…

气膜羽毛球馆如何提升运动体验—轻空间

随着人们对健康和运动的关注度日益增加,羽毛球作为一项受欢迎的运动,得到了越来越多人的喜爱。而气膜羽毛球馆,以其独特的优势,正在改变传统羽毛球馆的运动体验。那么,气膜羽毛球馆是如何提升运动体验的呢?…

神经网络 torch.nn---Non-Linear Activations (ReLU)

ReLU — PyTorch 2.3 documentation torch.nn - PyTorch中文文档 (pytorch-cn.readthedocs.io) 非线性变换的目的 非线性变换的目的是为神经网络引入一些非线性特征,使其训练出一些符合各种曲线或各种特征的模型。 换句话来说,如果模型都是直线特征的…

C#之EntityFramework的应用

目录 1,名词概述。 2,实体数据模型EDM介绍。 3,规范函数。 4,查看Linq转换成的SQL语句。 5,数据的增删改查。 5.1,数据查询 5.2,数据插入 5.3,数据更新 5.4,数据…

【android】设置背景图片

改变值&#xff0c;可显示zai在 在theves下面的两个value都要增加名字代码 <item name"windowActionBar">false</item><item name"android:windowNoTitle">true</item><item name"android:windowFullscreen">tru…

Base64前端图片乱码转换

title: Base64码乱转换 date: 2024-06-01 20:30:28 tags: vue3 后端图片前端显示乱码 现象 后端传来一个图片&#xff0c;前端能够接收&#xff0c;但是console.log()后发现图片变成了乱码&#xff0c;但是检查后台又发现能够正常的收到了这张图片。 处理方法 笔者有尝试将…

联想Y410P跑大模型

安装vs 2017 查看GPU版本 查看支持哪个版本的cuda windows cuda更新教程_cuda 12.0-CSDN博客 下载并安装cuda tookit 10.1 CUDA Toolkit 10.1 Update 2 Archive | NVIDIA Developer 找到下载的文件&#xff0c;安装 参考安装链接 Win10 Vs2017 CUDA10.1安装&#xff08;避坑…

【C语言】10.C语言指针(4)

文章目录 1.回调函数是什么&#xff1f;2.qsort 使⽤举例2.1 使⽤qsort函数排序整型数据2.2 使⽤qsort排序结构数据 3.qsort函数的模拟实现 1.回调函数是什么&#xff1f; 回调函数就是一个通过函数指针调用的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数…

kafka-消费者-指定offset消费(SpringBoot整合Kafka)

文章目录 1、指定offset消费1.1、创建消费者监听器‘1.2、application.yml配置1.3、使用 Java代码 创建 主题 my_topic1 并建立3个分区并给每个分区建立3个副本1.4、创建生产者发送消息1.4.1、分区0中的数据 1.5、创建SpringBoot启动类1.6、屏蔽 kafka debug 日志 logback.xml1…

服务器数据恢复—EqualLogic存储硬盘灯亮黄色的数据恢复案例

服务器数据恢复环境&#xff1a; 一台某品牌EqualLogic PS 6011型号存储&#xff0c;底层有一组由16块SAS硬盘组建的RAID5阵列&#xff0c;上层存储空间划分了4个卷&#xff0c;格式化为VMFS文件系统&#xff0c;存放虚拟机文件。 服务器故障&#xff1a; 存储设备上两块硬盘指…

基于STC89C52单片机空气PM2.5系统设计资料

#include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned char //宏定义sbit RSP1^6;//液晶接口sbit ENP1^7;sbit LED P2^0;//粉尘传感器控制接口sbit ADCS P3^7;//AD0832接口sbit ADCLK P3^5;sbit ADDI P3^6;sbit ADDO P3^6;…

【大模型】基于Hugging Face调用及微调大模型(1)

文章目录 一、前言二、Transformer三、Hugging Face3.1 Hugging Face Dataset3. 2 Hugging Face Tokenizer3.3 Hugging Face Transformer3.4 Hugging Face Accelerate 四、基于Hugging Face调用模型4.1 调用示例4.2 调用流程概述4.2.1 Tokenizer4.2.2 模型的加载4.2.3 模型基本…

# RocketMQ 实战:模拟电商网站场景综合案例(二)

RocketMQ 实战&#xff1a;模拟电商网站场景综合案例&#xff08;二&#xff09; 一、SpringBoot 整合 Dubbo &#xff1a;dubbo 概述 1、dubbo 概述 Dubbo &#xff1a;是阿里巴巴公司开源的一款高性能、轻量级的 Java RPC 框架&#xff0c;它提供了三大核心能力&#xff1a…