golang遍历时修改被遍历对象
前言
很多时候需要将遍历对象中去掉某些元素,或者往遍历对象中添加元素,这时候就需要小心操作了。
对于go语言中的一些注意事项我做了总结和示例,留下点笔记。
遍历切片
- 遍历切片时去掉元素,错误示例:
func main() {
arr := []int{1, 2, 3, 4}
for i := range arr {
if arr[i] == 3 {
arr = append(arr[:i], arr[i+1:]...)
}
}
fmt.Println(arr)
}
最终报错
panic: runtime error: index out of range [3] with length 3
,因为range在迭代时已经确定i的范围为[0,len(arr))的左闭右开的区间。
但是当满足arr[i] == 3
时对arr进行了修改,缩短了arr的长度,此时len(arr)=3,最大下标为2,因此当执行arr[3]时会报错。
- 遍历切片时去掉元素,不会报错,但不建议的写法:
func main() {
arr := []int{1, 2, 3, 4}
for i, v := range arr {
fmt.Println(i, v)
if v == 3 {
arr = append(arr[:i], arr[i+1:]...)
// arr = []int{4, 5, 6, 7} // 可以将上一行代码替换,看最终遍历的i,v情况
}
}
fmt.Println(arr)
}
还是回到range的用法,当执行for循环时就已经确定(i,v)的遍历元素值,及时循环过程中修改arr,也不会改变for要遍历的(i,v)值。
可以将上面代码修改一下,看下在循环中改变arr值时,后面遍历的(i,v)是不会随着arr的改变而改变的。
- 遍历切片时去掉元素,建议写法:
func main() {
arr := []int{1, 2, 3, 4}
for i := 0; i < len(arr); i++ {
fmt.Println(i, arr[i])
if arr[i] == 3 {
arr = append(arr[:i], arr[i+1:]...)
i--
}
}
fmt.Println(arr)
}
该方案只修改i的值,在删除元素时进行i--,可以确保遍历arr没有问题,而且每次通过arr[i]获取切片值不存在问题。
当然用该方式也可以在遍历时添加元素,只要i也对应变化就没问题。
遍历map
for key := range m {
if key.expired() {
delete(m, key)
}
}
- 清空map所有元素,如下第一种是省事的写法,第二种不会产生新的对象,用哪种看个人喜好吧。
m = make(map[int]int) // 可以产生一个新对象,旧对象等着被垃圾回收
for k := range m {
delete(m,k) // 循环遍历并删除map所有元素,好处是map缓存还在,下次添加时可直接使用缓存
}
总结
关于切片遍历时进行操作需要注意一些坑。
关于map遍历时进行操作相对坑少点,不过遍历map需要修改元素时,map的value要为指针类型,这点得谨记。
golang遍历时修改被遍历对象的更多相关文章
- 21、List遍历时修改元素的问题
List迭代时修改元素的问题 请编写代码完成以下需求:判断一个List里面是否包含monkey,如果包含的话,向集合中添加1024这个字符串.‘ package com.monkey1024.list ...
- List集合遍历时修改元素出现并发修改异常总结
什么是并发修改异常: 当我们在遍历实现了collection接口与iterator接口的集合时(List.Set.Map), 我们可以通过遍历索引也可以通过迭代器进行遍历.在我们使用迭代器进行遍历集合 ...
- 不要在遍历子结点时修改parent
[不要在遍历子结点时修改parent] 在用for/foreach遍历子结点时,如果在这过程中有改变子结点的parent,会导致不可预料的结果.我所遇到的问题是,在此种情况下,并非所有的子结点都能遍历 ...
- C++进阶 STL(3) 第三天 函数对象适配器、常用遍历算法、常用排序算法、常用算数生成算法、常用集合算法、 distance_逆序遍历_修改容器元素
01昨天课程回顾 02函数对象适配器 函数适配器是用来让一个函数对象表现出另外一种类型的函数对象的特征.因为,许多情况下,我们所持有的函数对象或普通函数的参数个数或是返回值类型并不是我们想要的,这时候 ...
- JAVA的Hashtable在遍历时的迭代器线程问题
这篇博客主要讲什么 Hashtable及其内部类的部分源码分析 Hashtable在遍历时的java.util.ConcurrentModificationException异常的来由和解决 单机在内 ...
- 【原理探究】女朋友问我ArrayList遍历时删除元素的正确姿势是什么?
简介 我们在项目开发过程中,经常会有需求需要删除ArrayList中的某个元素,而使用不正确的删除方式,就有可能抛出异常.或者在面试中,会遇到面试官询问遍历时如何正常删除元素.所以在本篇文章中,我们会 ...
- jackson中JSON字符串节点遍历和修改
有些场景下,在实现一些基础服务和拦截器的时候,我们可能需要在不知道JSON字符串所属对象类型的情况下,对JSON字符串中的某些属性进行遍历和修改,比如,设置或查询一些报文头字段. 在jackson中, ...
- Java遍历时删除List、Set、Map中的元素(源码分析)
在对List.Set.Map执行遍历删除或添加等改变集合个数的操作时,不能使用普通的while.for循环或增强for.会抛出ConcurrentModificationException异常或者没有 ...
- 【Java】List遍历时删除元素的正确方式
当要删除ArrayList里面的某个元素,一不注意就容易出bug.今天就给大家说一下在ArrayList循环遍历并删除元素的问题.首先请看下面的例子: import java.util.ArrayLi ...
随机推荐
- 题解 CF1437G Death DBMS
这题感觉不是很难,但是既然放在 \(\texttt{EDU}\) 的 \(\texttt{G}\) 题,那么还是写写题解吧. \(\texttt{Solution}\) 首先看到 "子串&q ...
- python命名切片
命名切片 c = slice(2, 5) a = [1, 2, 3, 4, 5, 6, 7] print(a[c])
- 六、Jmeter测试元件-测试计划
启动Jmeter时,会默认建好一个测试计划,启动一个Jmeter只有个测试计划 测试用到的源码下载地址 https://www.cnblogs.com/fanfancs/p/13557062.html ...
- centos 7.0下安装MySQL 5.7.26
1.下载MySQL 5.7.26安装包,卸载自带MySQL数据库 yum remove mariadb-libs -y yum install -y libaio-devel 2.上传MySQL 5. ...
- Python高级语法-私有属性-with上下文管理器(4.7.3)
@ 目录 1.说明 2.代码 关于作者 1.说明 上下文管理器 这里使用with open操作文件,让文件对象实现了自动释放资源.我们也能自定义上下文管理器,通过__enter__()和__exit_ ...
- Python高级语法-对象实例对象属性-类与实例,class方法静态方法等(4.6.1)
@ 目录 1.说明 2.代码 关于作者 1.说明 python中属性:类属性,实例属性 方法:类方法,实例方法,静态方法 想修改类属性,只能是类方法,因为只有类方法把cls(类)传入数据里面 静态方法 ...
- 【漏洞复现】Struts2-045分析(CVE-2017-5638)
如果需要大佬写好的脚本,可以直接去github上面搜 struts2 - 045 一个还比较出名的漏洞,因为涉及到利用Gopher协议反弹shell,所以写篇文章来简单学习下这个漏洞. Struts2 ...
- P4735 最大异或和 01 Trie
题目描述 给定一个非负整数序列 \(\{a\}\),初始长度为\(n\). 有 \(m\) 个操作,有以下两种操作类型: \(A\ x\):添加操作,表示在序列末尾添加一个数 \(x\),序列的长度 ...
- 每天学习一点ES6(二)let 和 const
let 命令 let 和 var 差不多,只是限制了有效范围. 先定义后使用 不管是什么编程语言,不管语法是否允许,都要秉承先定义,然后再使用的习惯,这样不会出幺蛾子.以前JavaScript比较随意 ...
- 使用Ubuntu手动安装NextCloud
p.p1 { margin: 0; font: 11px Menlo; color: rgba(0, 0, 0, 1) } span.s1 { font-variant-ligatures: no-c ...