標籤:int 中間 returns main Go語言 地址 stack 代碼 href
本篇系轉載
在使用go的container/list的package時,你可能會無意間踩一個小坑,那就是list的迴圈刪除元素。
list刪除元素,直觀寫下來的代碼如下:
package mainimport ( "container/list" "fmt")func main() { //初始化一個list l := list.New() l.PushBack(1) l.PushBack(2) l.PushBack(3) l.PushBack(4) 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 1After Removing...234
從結果可以看出,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 mainimport ( "container/list" "fmt")func main() { l := list.New() l.PushBack(1) l.PushBack(2) l.PushBack(3) l.PushBack(4) 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 1removing 2removing 3removing 4After Removing...
轉載地址: http://ju.outofmemory.cn/entry/79972
go語言從零學起(三)--list迴圈刪除元素(轉載)