理解 Go 中的切片:append 操作的深入分析(篇1)

news2024/12/23 7:26:49

理解 Go 语言中 slice 的性质对于编程非常有益。下面,我将通过两个代码示例来解释切片在不同函数之间传递并执行 append 操作时的具体表现。

本篇为第 1 篇,当切片的容量 cap 充足时

第一份代码

slice1 的初始长度为 3,容量为 10

func main() {
	slice1 := make([]int, 3, 10)
	fmt.Println("slice 1:", slice1, len(slice1), cap(slice1))

	test1(slice1)
  
	fmt.Println("slice 1:", slice1, len(slice1), cap(slice1))
  
  // 此时若访问 slice1[3] 则 panic,因为 len = 3,不可越界 len
  // fmt.Println( slice[3] )
}

func test1(slice2 []int) {
	// slice 2 对切片进行 append 操作
	slice2 = append(slice2, 1)
	fmt.Println("slice 2:", slice2, len(slice2), cap(slice2))
}

输出:

slice 1[0 0 0] 3 10
slice 2[0 0 0 1] 4 10
slice 1[0 0 0] 3 10

我们可以观察到,在 main 函数中,slice2 对切片的改动并没有体现在 slice1 上,尽管它们明显操作的是同一底层数组。为什么会这样呢?

原来,在上述第一份代码中,slice2 = append(slice2, 1) 这一行操作是在函数 test1 内部执行的,所以它不会改变调用该函数的 main 函数中的 slice1 的长度 len = 3,只会改变 test1 函数内部的 slice2 长度 len = 4。因此,在 main 函数中,由于 slice1 的长度仍然是 3,我们自然无法“看到”第 4 个元素。

那么,如果在 main 函数中继续对 slice1 执行 append 操作会发生什么呢?答案是,它会直接覆盖掉 test1 函数中对第 4 个元素的赋值!具体的情况如下图所示:

切片append_流程图

第二份代码

有了上面的解释后,我们可以自然而然的写出下面代码验证上述逻辑:

// 以下注释为执行时机,按顺序为 1 2 3:
func main() {
	slice1 := make([]int, 3, 10)
	fmt.Println("slice 1:", slice1, len(slice1), cap(slice1))

	go test1(slice1)
	time.Sleep(1 * time.Second)

	slice1 = append(slice1, 2) // 2

	fmt.Println("slice 1:", slice1, len(slice1), cap(slice1)) // 2

	time.Sleep(4 * time.Second)
}

func test1(slice2 []int) {
	slice2 = append(slice2, 1) // 1
	time.Sleep(2 * time.Second)
	fmt.Println("slice 2:", slice2, len(slice2), cap(slice2)) // 3
}

输出:

slice 1[0 0 0] 3 10
slice 1[0 0 0 2] 4 10
slice 2[0 0 0 2] 4 10

结论

  • 当我们在函数 A 中将 slice1 传递给函数 B 并在 B 中执行 append 操作时,只要底层数组没有扩张,就会在原数组的基础上进行追加,此时 B 函数中的 len 为 4。
  • 虽然 A 和 B 函数共享一个底层数组,但由于 A 函数的 len 保持为 3,因此我们不能访问数组的第 4 位元素,否则会引发 panic。
  • 当我们在 A 函数中也执行 append 操作时,A 函数会直接覆盖底层数组的第 4 位数值,从而直接覆盖了 B 函数所赋的值。

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

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

相关文章

win10电脑右下角不显示电脑图标,但是能正常上网,怎么解决?

一、问题描述 win10系统更新后,电脑右下角不显示小电脑图标,但是能正常上网,而且用命令测试时显示的是192打头的网址。 二、解决方法 运行命令提示符窗口,在命令提示符中输入:netsh winsock reset( 如果提示…

汇编知识点之磁盘文件存取技术

1.文件代号式磁盘存取 (1)两个重要的表 (2)简要说明: 文件代号式存取方式将有关文件的各种信息都包括在DOS中。 在处理指定文件时必须使用一个完整的路径名,一旦文件的路径名被送入操作系统,就被赋予一个简单的文件…

使用chatGPT规划在北京的生活预算

介绍 通过使用chatGPT大概预算自己的生活支出和收入,搞清楚多少的收入能在一个城市过的比较舒服,更好的去规划自己的职业和未来。本文以一线城市为例。 什么是生活成本指数? 生活成本指数是对居住在某个地点的普通人预期的不同费用成本的广泛…

十秒搞懂ER图中的对应关系

十秒搞懂ER图中的对应关系 ER图是什么实体是什么关系如何确认实体间的关系简单总结 ER图是什么 实体关系图(Entity-Relationship Diagram,简称ER图)是一种图形化的工具,用于表示数据库中不同实体之间的关系和连接。ER图是数据库设…

Ubuntu系统没有声音

现象 新按转的Ubuntu系统没有声音,怀疑是声卡选择的问题 解决方法 1、在终端输入alsamixer命令 2、按下F6键选择声卡 不要选择NVidia,而是选择HD-Audio 3、将所有音量调到最大,把disable调成enable

2023-08-14 linux 串口终端输入长命令不换行,覆盖前面内容,stty命令设置串口终端行列数

一、linux 串口终端输入长命令不换行,覆盖前面内容,现象如下图: 二、解决方法:用stty 命令设置行列数 stty columns 200 stty rows 10三、参考文章 https://www.cnblogs.com/goloving/p/15170537.html 常用Linux串口设备操作命…

Tomcat多实例部署及nginx+tomcat的负载均衡和动静分离

Tomcat多实例部署 安装 jdk、tomcat(流程可看之前博客) 配置 tomcat 环境变量 [rootlocalhost ~]# vim /etc/profile.d/tomcat.sh#tomcat1 export CATALINA_HOME1/usr/local/tomcat/tomcat1 export CATALINA_BASE1/usr/local/tomcat/tomcat1 export T…

达梦数据库(dm8) 在Centos7环境 单节点安装

国产数据库-达梦 一、环境详情二、Centos7 参数优化三、创建用户四、开始安装 当前安装 在指定版本环境下 测试,仅供参考 一、环境详情 软件版本 软件版本下载地址Centos 7CentOS Linux release 7.9.2009 (Core) x86达梦数据库dm8_20230418_x86_rh6_64.zip 节点分配…

html2canvas生成图片地址Base64格式转成blob在转成file(二进制)可正常发送(保姆教程,复制粘贴可用)

开始: 最终结果: 1. html2canvas方法生成的图片地址已Base64编码形式放在img标签src中可直接展示生成的图片(注意页面标签获取位置,还有个setTimeout页面渲染需要时间) setTimeout(function () {var result {};v…

最新Anaconda安装-保姆级教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Anaconda下载 二、使用步骤 手动配置环境变量 (上面选择just me和默认配置的可以跳过这一步) 简要说明五条路径的用途:这五…

Spring(三):Spring中Bean的生命周期和作用域

前言 在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean。简单地讲,bean 就是由 IOC 容器初始化、装配及管理的对象,除此之外,bean 就与应用程序中的其他对象没有什么区别了。而 b…

金蝶云星空和易快报单据接口对接

金蝶云星空和易快报单据接口对接 来源系统:易快报 易快报是敏捷的企业报销费控与聚合消费平台,为企业提供移动报销、聚合消费、全程费控、预算管理、发票管理等一站式解决方案。同时,易快报可集成多家银行及第三方支付平台,打通对公对私付款&…

GD32F103VE使用软件扫描读取多通道AD值

GD32F103VE使用软件扫描读取多通道AD值。 GD32F103的ADC为12位AD转换器,ADC转换结果保存在16位数据寄存器中; 模拟输入通道: 16个外部模拟输入通道; 1个内部温度传感器通道(Vsense) 1个内部参考电压输入通道(VrefInt) ADC的VDDA电源引脚需要接入3.3V; ADC输入模拟…

Algorithem Review 5.2 图论

网络流 设源点为 s s s,汇点为 t t t,每条边 e e e 的流量上限为 c ( e ) c(e) c(e),流量为 f ( e ) f(e) f(e)。割 指对于某一顶点集合 P ⊂ V P \subset V P⊂V,从 P P P 出发指向 P P P 外部的那些原图中的边的集合&a…

WMS系统出库操作规范:提高效率与准确性的关键

WMS系统出库管理是指通过仓库管理系统(Warehouse Management System,简称WMS)对仓库中的货物进行出库操作的管理过程。WMS系统是一种利用自动化和数字化技术提高仓库管理效率和准确性的工具,它提供了对仓库内货物的全面控制和可视…

CentOS7源码安装MySQL详细教程

😊 作者: Eric 💖 主页: https://blog.csdn.net/weixin_47316183?typeblog 🎉 主题:CentOS7源码安装MySQL详细教程 ⏱️ 创作时间: 2023年08月014日 文章目录 1、安装的四种方式2、源码安装…

selenium的环境搭建

selenium是一个自动化测试框架,主要针对web项目进行UI自动化。他的工作原理如下图: 那么我们在学习selenium之前就需要就行一个环境的搭建,就是要下载配置我们的浏览器驱动。进入正题: CNPM Binaries Mirror 在网站中选择对应自…

五种方法,教你如何在Mac上查看文件完整路径

在MacOS上,Finder显示文件默认是不带路径展示的,你进入某个文件夹只会显示文件夹的名称而已,如下图: 那如何获取或者显示文件的完整路径呢?在MacOS中有五种方法可以显示文件完整路径。 第一种:使用【终端】…

go入门实践四-go实现一个简单的tcp-socks5代理服务

文章目录 前言socks协议简介go实现一个简单的socks5代理运行与压测抓包验证 前言 SOCKS是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递。协议在应用层和传输层之间。 本文使用先了解socks协议。然后实现一个socks5的tcp代理服务端。最后&#…

excel填数据转json格式

定制化比较严重,按需更改 excel文件如下 代码 # -*- coding: utf-8 -*- import oss2 import shutil import sys import xlwt import xlrd import json from datetime import datetime, timedeltafile1 "C:\\Users\\cxy\\Desktop\\generate.xls" #打开表…