【切片】基础不扎实引发的问题
本次文章主要是来聊聊关于切片传值需要注意的问题,如果不小心,则很容易引发线上问题,如果不够理解,可能会出现奇奇怪怪的现象
问题情况:
小 A 负责一个模块功能的实现,在调试代码的时候可能不仔细,部署到线上环境时发现在现有策略列表上追加新的策略时,总是无法生效,这是为什么呢?
追查代码后发现问题出在关于切片的使用上出了认知偏差,小 A 认为 golang 中,传切片就是传引用,因此写出了这样的代码片段
func xxxFunc(sli []int ,newSli []int) {// ... 省略部分代码sli = append(sli, newSli...)// ... 省略部分代码return
}
想表达的意思是:
传入的 sli 切片属于旧切片,期望在 sli 切片上追加 newSli 中的元素,最终期望得到的 sli 里面是包含 newSli 元素的
然而,对于 Golang 中切片 slice 有一定了解的 xdm 就很清楚,这样写其实并没有什么实际作用,在 Golang 中传参都是传值而不是传地址
因此此处传入的 sli 切片,也仅仅是一个拷贝而已,在 xxxFunc 函数中的 sli 切片被修改了,实际上是不会影响函数外部的 sli 的
那么对于切片此处做几个阐述
首先强调几点关于切片的注意事项
- Golang 中的函数参数,都是传值,不是传地址
- 对于切片自身的底层数据结构,我们可以通过索引的方式拿到底层数组的地址,并修改其地址上的值,例如
sli[2] = "hello"
,这是可以直接修改
-
如果传入的切片,期望实参也能够被改变的话,那么就需要想办法修改切片的底层数组
- 通过传切片的地址,也就是传指针的方式
- 在函数中,去索引切片的底层数组地址,进行修改数据
案例 1 遍历的时候修改
通过 value 修改切片值 - 不靠谱
我们给出一个切片 var mySlice = []int{7, 8, 9}
,并编写如下几个函数来查看是否会对原有切片数据有影响
func main() {log.SetFlags(log.Lshortfile)var mySlice = []int{7, 8, 9}log.Printf("mySlice == %+v", mySlice)log.Println("---------------------------------------------")mySliceDemo := testDemo(mySlice)log.Printf("mySlice == %+v ,mySliceDemo == %+v", mySlice, mySliceDemo)log.Printf("mySlice == %p ,mySliceDemo == %p", &mySlice, &mySliceDemo)
}func testDemo(sli []int) []int {for _, value := range sli {value *= 2}return sli
}
给 testDemo 传入 mySlice 切片,在函数内部通过 for…range 的方式去修改切片内元素的值,然而代码中的 value 仍然是一个拷贝,他并不会真的对外部的 mySlice 有任何影响,结果自然是这样的
可以通过修改切片索引上的值
当然如果我们这样写,去找到索引对应的底层数组的地址,再修改其地址上的值,是可行的
func testDemo2(sli []int) []int {for index, _ := range sli {sli[index] *= 2}return sli
}
自然通过指针的方式仍然可以
传入的这个指针,实际上也是一个拷贝,只不过拷贝的是这个指针,也就是指针自身的地址不一样,但是他们指向的底层数组是一样的,因此可以直接修改
这种修改的方式,也是去修改地址上的值,因此有效
func testDemo3(sli *[]int) {for index, _ := range *sli {(*sli)[index] *= 2}return
}
结果自然 ok,原有 mySlice
的地址也是没有发生变化的,只是值发生了变化
案例 2 使用 append 会有什么不同
那么如果是在子函数里面使用 append 追加数据,是否会有不同的效果?
func appendDemo(sli []int) []int {sli = append(sli, 999)return sli
}
实际上,此处传入的仍然是 mySlice 的拷贝,appendDemo 中使用 append,也是基于拷贝后的值来进行数据追加
哪怕是遇到切片扩容的情况,也仅仅是对于函数内的拷贝副本来进行扩容和变化,例如这样
func appendDemo3(sli []int)[]int{sli = append(sli, []int{3,4}...)return sli
}
传入切片的地址
在使用 append 的情况, 向函数参数中传入切片的指针,此处对于函数来说,仍然是一个副本,只不过这个副本是指针,指向的底层数组仍然是和 mySlice 是一样的,因此可以通过这个拷贝的指针去修改实际底层数组的值
func appendDemo2(sli *[]int){*sli = append(*sli, []int{1000,10001}...)return
}
可以看到使用指针的方式,处理起来还是妥妥的,在 appendDemo2 中实际修改了 mySlice 的值,且也是我们所期望的
至此,对于文章开头问题的解决方式,xdm 心中都有数了吧,那就不能再犯了吧,希望能够给你带来帮助
感谢阅读,欢迎交流,点个赞,关注一波 再走吧
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是阿兵云原生,欢迎点赞关注收藏,下次见~
文中提到的技术点,感兴趣的可以查看这些文章:
- 你以为传切片就是传引用了吗?
- 你真的知道 GO 中 nil 代表什么吗?
- GO 中 slice 的实现原理
- 微服务线上问题排查困难?不知道问题出在哪一环?那是你还不会分布式链路追踪
- k8s 服务升级为啥 pod 会部署到我们不期望的节点上??看来你还不懂污点和容忍度
可以进入地址进行体验和学习:https://xxetb.xet.tech/s/3lucCI
相关文章:
【切片】基础不扎实引发的问题
本次文章主要是来聊聊关于切片传值需要注意的问题,如果不小心,则很容易引发线上问题,如果不够理解,可能会出现奇奇怪怪的现象 问题情况: 小 A 负责一个模块功能的实现,在调试代码的时候可能不仔细&#x…...
CVE-2023-5129 libwebp堆缓冲区溢出漏洞影响分析
漏洞简述 近日苹果、谷歌、Mozilla和微软等公司积极修复了libwebp组件中的缓冲区溢出漏洞,相关时间线如下: 9月7日,苹果发布紧急更新,修复了此前由多伦多大学公民实验室报告的iMessage 0-click 漏洞,漏洞被认为已经被…...
leetcode做题笔记155. 最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…...
蓝海彤翔亮相2023新疆网络文化节重点项目“新疆动漫节”
9月22日上午,2023新疆网络文化节重点项目“新疆动漫节”(以下简称“2023新疆动漫节”)在克拉玛依科学技术馆隆重开幕,蓝海彤翔作为国内知名的文化科技产业集团应邀参与此次活动,并在美好新疆e起向未来动漫展映区设置展…...
【AI视野·今日NLP 自然语言处理论文速览 第四十四期】Fri, 29 Sep 2023
AI视野今日CS.NLP 自然语言处理论文速览 Fri, 29 Sep 2023 Totally 45 papers 👉上期速览✈更多精彩请移步主页 Daily Computation and Language Papers MindShift: Leveraging Large Language Models for Mental-States-Based Problematic Smartphone Use Interve…...
【VsCode】vscode创建文件夹有小图标显示和配置
效果 步骤 刚安装软件后, 开始工作目录下是没有小图标显示的。 如下图操作,安装vscode-icons 插件,重新加载即可 创建文件夹,显示图标如下:...
celery分布式异步任务队列-4.4.7
文章目录 celery介绍兼容性简单使用安装使用方式 功能介绍常用案例获取任务的返回值任务中使用logging定义任务基类 任务回调函数No result will be storedResult will be stored任务的追踪、失败重试 python setup.py installln -s /run/shm /dev/shmOptional configuration, …...
解决M2苹果芯片Mac无法安装python=3.7的虚拟环境
问题描述 conda无法安装python3.7的虚拟环境: conda create -n py37 python3.7出现错误 (base) ➜ AzurLaneAutoScript git:(master) conda create -n alas python3.7.6 -y Collecting package metadata (current_repodata.json): done Solving environment: fa…...
Sound/播放提示音, Haptics/触觉反馈, LocalNotification/本地通知 的使用
1. Sound 播放提示音 1.1 音频文件: tada.mp3, badum.mp3 1.2 文件位置截图: 1.3 实现 import AVKit/// 音频管理器 class SoundManager{// 单例对象 Singletonstatic let instance SoundManager()// 音频播放var player: AVAudioPlayer?enum SoundOption: Stri…...
Oracle实现主键字段自增
Oracle实现主键自增有4种方式: Identity Columns新特性自增(Oracle版本≥12c)创建自增序列,创建表时,给主键字段默认使用自增序列创建自增序列,使用触发器使主键自增创建自增序列,插入语句&…...
【C++数据结构】二叉树搜索树【完整版】
目录 一、二叉搜索树的定义 二、二叉搜索树的实现: 1、树节点的创建--BSTreeNode 2、二叉搜索树的基本框架--BSTree 3、插入节点--Insert 4、中序遍历--InOrder 5、 查找--Find 6、 删除--erase 完整代码: 三、二叉搜索树的应用 1、key的模型 &a…...
TouchGFX之字体缓存
使用二进制字体需要将整个字体加载到存储器。 在某些情况下,如果字体很大,如大字号中文字体,则这样做可能不可取。 字体缓存使应用能够从外部存储器只能加载显示字符串所需的字母。 这意味着整个字体无需保存到在可寻址闪存或RAM上ÿ…...
windows系统关闭软件开机自启的常用两种方法
win10中安装软件时经常会默认开机自启动,本文主要介绍两种关闭软件开机自启动方法。 方法1 通过任务管理器设置 1.在任务管理器中禁用开机自启动:打开任务管理器,右键已启动的软件,选择禁用。 方法2 通过windows服务控制开机自启…...
巧用@Conditional注解根据配置文件注入不同的bean对象
项目中使用了mq,kafka两种消息队列进行发送数据,为了避免硬编码,在项目中通过不同的配置文件自动识别具体消息队列策略。这里整理两种实施方案,仅供参考! 方案一:创建一个工具类,然后根据配置文…...
论文笔记(整理):轨迹相似度顶会论文中使用的数据集
0 汇总 数据类型数据名称数据处理出租车数据波尔图 原始数据:2013年7月到2014年6月,170万条数据 ICDE 2023 Contrastive Trajectory Similarity Learning with Dual-Feature Attention 过滤位于城市(或国家)区域之外的轨迹 过…...
Python实现单例模式
使用函数装饰器 def singleton(cls):_instance {}def inner():if cls not in _instance:_instance[cls] cls()return _instance[cls]return innersingleton class Demo(object):def __init__(self):passdef test():b1 Demo()b2 Demo()print(b1, b2)使用类装饰器 class si…...
spark相关网站
Spark的五种JOIN策略解析 https://www.cnblogs.com/jmx-bigdata/p/14021183.html 万字详解整个数据仓库建设体系(好文值得收藏) https://mp.weixin.qq.com/s?__bizMzg2MzU2MDYzOA&mid2247484692&idx1&snf624672e62ba6cd4cc69bdb6db28756a&…...
ThreeJS-3D教学四-光源
three模拟的真实3D环境,一个非常炫酷的功能便是对光源的操控,之前教学一中已经简单的描述了多种光源,这次咱们就详细的讲下一些最常见的光源: AmbientLight 该灯光在全局范围内平等地照亮场景中的所有对象。 该灯光不能用于投射阴…...
Linux 回收内存到底怎么计算anon/file回收比例,只是swappiness这么简单?
概述 Linux内核为了区分冷热内存,将page以链表的形式保存,主要分为5个链表,除去evictable,我们主要关注另外四个链表:active file/inactive file,active anon和inactive anon链表,可以看到这主要分为两类,file和anon page,内存紧张的时候,内核开始从inactive tail定…...
软件测试中的测试工具和自动化测试
1. 测试工具 测试工具也分为不同人员使用的 开发人员:测试框架,编写测试用例;各类线上dump分析工具如windgb;开发时的集成IDE工具如Visual Studio,idea等等 面向不同测试需求的测试工具 软件测试是软件开发生命周期…...
个人博客系统测试报告
个人博客系统测试报告 一.项目背景二.项目功能三.测试用例3.1 功能测试3.2 自动化测试(部分测试)3.2.1登陆页面3.2.2博客详情页3.2.3博客编辑页3.2.4个人列表页3.2.5测试结果 3.3 性能测试 一.项目背景 当学习完一项技能后,我们总会习惯通过博…...
高效搜索,提升编程效率
一、搜索效率 1.1魔法上网 网址: 一个很变态但可以让你快速学会计算机的方法…………_哔哩哔哩_bilibili 谷歌镜像: https://search.fuyeor.com/zh-cn/Google 谷歌学术: https://link.zhihu.com/?targethttps%3A//scholar.lanfanshu.cn/…...
Java编程技巧:文件上传、下载、预览
目录 1、上传文件1.1、代码1.2、postman测试截图 2、下载resources目录中的模板文件2.1、项目结构2.2、代码2.3、使用场景 3、预览文件3.1、项目结构3.2、代码3.3、使用场景 1、上传文件 1.1、代码 PostMapping("/uploadFile") public String uploadFile(Multipart…...
【蓝桥杯选拔赛真题63】Scratch云朵降雨 少儿编程scratch图形化编程 蓝桥杯选拔赛真题解析
目录 scratch云朵降雨 一、题目要求 编程实现 二、案例分析 1、角色分析...
【新版】系统架构设计师 - 软件架构的演化与维护
个人总结,仅供参考,欢迎加好友一起讨论 文章目录 架构 - 软件架构的演化与维护考点摘要软件架构演化和定义面向对象软件架构演化对象演化消息演化复合片段演化约束演化 软件架构演化方式静态演化动态演化 软件架构演化原则软件架构演化评估方法大型网站架…...
安卓循环遍历计时器
计时器循环遍历 计时器的使用 我习惯两种方式如下: 第一种使用 handler: 1,初始化 声明 public static final int REGULAR_TIME 1000; //1秒 时间间隔private Handler mUiHandler;private int index0;Runnable runnable new Runnable()…...
Docker-基本了解
Docker-基本了解 一、基本概念1、镜像2、容器 二、执行流程三、体系结构 一、基本概念 Docker是容器化平台,提供应用打包,部署与运行应用的容器化平台,应用程序通过docker engine(Docker 引擎获取可用资源)࿰…...
Leetcode383. 赎金信
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每…...
overleaf杂谈-Springer文献格式问题
目录 overleaf写作问题记录1.Latex中的%问题(文本变成灰色)2.Springer文献格式问题2.1 新建reference.bib2.2 谷歌学术搜索文章并引用2.3 复制BibTex2.4 复制进reference.bib2.5 在sn-article.tex的\end{document}前添加语句2.6 引用文献2.7 Springer模板…...
No148.精选前端面试题,享受每天的挑战和学习
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…...
wordpress 关键词堆砌/seo外包服务项目
1、概念 在代码块内,使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。 2、注意 “暂时性死区”也意味着typeof不再是一个百分之百安全的…...
晋城网站制作/seo推广需要多少钱
E5□C(E5AC/E5EC/E5CC/E5DC)温控器如何进行AT自整定?第一步:更改控制方式为PID首先在操作菜单下按上键或下键设定目标值,然后按菜单键3秒以上进入初始设定菜单,按模式键找到CNTL选项并设为PID,即控制方式为PID方式&…...
wordpress插件直播/国内十大搜索引擎
这两天对iptables这块做温习,受其他网友的启发,发现recent这个模块在线上的环境做ssh防护还是挺受用的。recent的使用实际也很简单,咱们先来看看其各个常用的参数--name #设定列表名称,默认DEFAULT。 --rsource …...
兼职做视频的网站/网页推广怎么做的
在TCP/IP协议中,TCP协议提供可靠的连接服务,採用三次握手建立一个连接。第一次握手:建立连接时,client发送syn包(synj)到server,并进入SYN_SENT状态,等待server确认&…...
天津电商网站建设/市场营销网络
在此示例中,您可以获取网页上所有出现的电子邮件地址。 如果您必须更改站点的特定页面或子部分的电子邮件地址,则很有用。 也可能对从网页上筛选爬网电子邮件地址有用,尽管这不是我在这里要实现的目标。 查看更多jQuery .each示例 。 i 不敏感…...
大连工业大学专升本/seo网站关键词优化快速官网
第一篇稿子,也是激励自己的。...