go语言从零学起(二)--list循环删除元素(转载)
本篇系转载
在使用go的container/list的package时,你可能会无意间踩一个小坑,那就是list的循环删除元素。
list删除元素,直观写下来的代码如下:
package main import (
"container/list"
"fmt"
) func main() {
//初始化一个list
l := list.New()
l.PushBack()
l.PushBack()
l.PushBack()
l.PushBack() fmt.Println("Before Removing...")
//遍历list,删除元素
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println("removing", e.Value)
l.Remove(e)
}
fmt.Println("After Removing...")
//遍历删除完元素后的list
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}
以上代码很简单,按常理来看,应该能得到正确的结果,list最后将会被清空。可事实却完全不是这样,执行后结果如下:
Before Removing...
removing
After Removing...
从结果可以看出,list根本没有清空,而只是删除了第一个元素。这是为何?原因就在container/list package的实现上了。这应该是我见过的实现最简单list了,出去注释也就100来行实现代码,而且它不只是一个简单链表,而且可以当做stack,当做queue来使用。
下面是Remove方法的代码:
// remove removes e from its list, decrements l.len, and returns e.
func (l *List) remove(e *Element) *Element {
e.prev.next = e.next
e.next.prev = e.prev
e.next = nil // avoid memory leaks
e.prev = nil // avoid memory leaks
e.list = nil
l.len--
return e
}
这下问题原因就明显了,就出现在e.next = nil 这行代码上。当执行玩remove,e.next就变成了nil,list遍历当然也就终止了。找出问题的原因,我们就容易找到workaround的办法了,将e.next用中间变量保存起来就OK了,代码如下:
package main import (
"container/list"
"fmt"
) func main() {
l := list.New()
l.PushBack()
l.PushBack()
l.PushBack()
l.PushBack()
fmt.Println("Before Removing...")
var n *list.Element
for e := l.Front(); e != nil; e = n {
fmt.Println("removing", e.Value)
n = e.Next()
l.Remove(e)
}
fmt.Println("After Removing...")
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}
执行结果如下:
Before Removing...
removing
removing
removing
removing
After Removing...
转载地址: http://ju.outofmemory.cn/entry/79972
go语言从零学起(二)--list循环删除元素(转载)的更多相关文章
- go语言从零学起(一) -- 文档教程篇
先记录一下自己学go语言的出发点 作为一个phper,精通一门底层语言一直是努力的目标. 相对于c,c++,go语言不需要过多的关注指针,内存释放,一两行代码就能跑起一个server服务,简直不要太简 ...
- go语言从零学起(三) -- chat实现的思考
要通过go实现一个应用场景: 1 建立一个websocket服务 2 维护在线用户的链接 3 推送消息和接受用户的操作 列出需求,很显然的想到了chat模型.于是研究了revel框架提供的sample ...
- go语言从零学起(四) -- 基于martini和gorilla实现的websocket聊天实例
如果只是想了解chat的实现方式,在gorilla和revel框架里面都有完整的chat实例可以提供参考.本篇讲解的是,如何基于martini实现websocket的聊天. 配置步骤: 1 已经安装了 ...
- 从零学脚手架(二)---初识webpack
在上一篇中,介绍了 webpack 的 entry . output . plugins 属性. 在这一篇,接着介绍其它配置属性. mode 这个属性在上一篇中使用过一次:设置 webpack 编译模 ...
- 带你从零学ReactNative开发跨平台App开发(二)
ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...
- 带你从零学ReactNative开发跨平台App开发[react native SqlLite 终极运用](十二)
ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...
- Web开发从零单排之二:在自制电子请帖中添加留言板功能,SAE+PHP+MySql
在上一篇博客中介绍怎样在SAE平台搭建一个html5的电子请帖网站,收到很多反馈,也有很多人送上婚礼的祝福,十分感谢! web开发从零学起,记录自己学习过程,各种前端大神们可以绕道不要围观啦 大婚将至 ...
- C语言老司机学Python (五)
今天看的是标准库概览. 操作系统接口: 用os模块实现. 针对文件和目录管理,还有个shutil模块可以用. 例句: import os os.getcwd() # 返回当前的工作目录 os.chdi ...
- 带你从零学ReactNative开发跨平台App开发(一)
ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...
随机推荐
- Scrum Meeting 报告
Scrum Meeting 报告 ----团队项目所需时间估计以及任务分配 由于能力有限,我们还不能构架好一个大框架.但是初步可以完成任务的流程和分配.任务所需要的具体实现可以参看<学霸系统的N ...
- Linux 基础入门第一次实验笔记
第一节.实验介绍 本节主要介绍 Linux 的历史,Linux 与 Windows 的区别等入门知识.如果你已经有过充分的了解,可以跳过本节,直接进入下一个实验. 一.Linux 为何物 Linux ...
- 奔跑吧DKY——团队Scrum冲刺阶段-Day 3
今日完成任务 各个成员今日完成的任务(如果完成的任务为开发或测试任务,需给出对应的Github代码签入记录截图:如果完成的任务为调研任务,需给出对应的调研总结博客链接:如果完成的任务为学习技术任务,需 ...
- Codeforces Round #196 (Div. 2) D. Book of Evil 树形dp
题目链接: http://codeforces.com/problemset/problem/337/D D. Book of Evil time limit per test2 secondsmem ...
- BETA-7
前言 我们居然又冲刺了·七 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 过去两天完成了哪些任务 经过分析发现,为提升速率估测的可靠性,目前最具可改造性的参数为帧间间隔,调用参 ...
- 批量梯度下降(BGD)、随机梯度下降(SGD)以及小批量梯度下降(MBGD)的理解
梯度下降法作为机器学习中较常使用的优化算法,其有着三种不同的形式:批量梯度下降(Batch Gradient Descent).随机梯度下降(Stochastic Gradient Descent ...
- NTP同步网络时间
为什么要同步网络时间呢,这是由于树莓派没有RTC和后备电池,不能像PC机那样关机之后仍可以走时. NTP对时步骤: 1 安装ntpdate sudo apt-get install ntpdate s ...
- 微信小程序公共组件的引用与控制
思路: 1.在组件wxml文件里实现布局.数据绑定.事件绑定: 2.组件js文件里定义事件,并将文件所有内容作为一个对象export出去:3.在引用的文件引入组件(方式有两种,一个是用include引 ...
- sqlserver trigger(触发器)-更新某几列数据时触发【转】
CREATE TRIGGER [dbo].[updataAlarmLevel]ON [dbo].[Alarm_Alarm_Info]AFTER INSERT, UPDATE – 在更新和插入之后ASB ...
- scrapy学习笔记(三):使用item与pipeline保存数据
scrapy下使用item才是正经方法.在item中定义需要保存的内容,然后在pipeline处理item,爬虫流程就成了这样: 抓取 --> 按item规则收集需要数据 -->使用pip ...