在go語言中,可以使用remove()函式來刪除list元素,語法“list物件.Remove(element)”,參數element表示要刪除清單元素。 element元素不能為空,如果不為空則傳回被刪除的元素的值,如果為空則會報異常。
本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。
go提供了一個list包,類似python的list,可以儲存任意類型的數據,並提供了相應的API,如下:
type Element func (e *Element) Next() *Element func (e *Element) Prev() *Element type List func New() *List func (l *List) Back() *Element func (l *List) Front() *Element func (l *List) Init() *List func (l *List) InsertAfter(v interface{}, mark *Element) *Element func (l *List) InsertBefore(v interface{}, mark *Element) *Element func (l *List) Len() int func (l *List) MoveAfter(e, mark *Element) func (l *List) MoveBefore(e, mark *Element) func (l *List) MoveToBack(e *Element) func (l *List) MoveToFront(e *Element) func (l *List) PushBack(v interface{}) *Element func (l *List) PushBackList(other *List) func (l *List) PushFront(v interface{}) *Element func (l *List) PushFrontList(other *List) func (l *List) Remove(e *Element) interface{}
其中,remove()函數用於列表list刪除元素,刪除的元素不能為空,如果為空,會報異常。
Remove(e *Element) interface{}
參數 | 描述 |
---|---|
e |
傳回值
傳回被刪除的元素的值。
package main import ( "container/list" "fmt" ) func main() { //使用 Remove 在列表中删除元素 listHaiCoder := list.New() listHaiCoder.PushFront("Hello") listHaiCoder.PushFront("HaiCoder") element := listHaiCoder.PushFront("Hello") removeEle := listHaiCoder.Remove(element) fmt.Println("RemoveElement =", removeEle) for i := listHaiCoder.Front(); i != nil; i = i.Next() { fmt.Println("Element =", i.Value) } }
我們透過list.New 建立了一個清單listHaiCoder,接著使用 PushFront 函數在清單中插入三個元素,接著使用Remove 函數刪除了最後插入的元素。
最後,我們印出被刪除的元素和刪除後的列表,Remove 函數傳回的是被刪除的元素的值,同時,我們發現最後插入的元素已經被成功從列表刪除了。範例2:刪除空元素
package main import ( "container/list" "fmt" ) func main() { //使用 Remove 在列表中删除空元素,报错 listHaiCoder := list.New() listHaiCoder.PushFront("Hello") listHaiCoder.PushFront("HaiCoder") listHaiCoder.Remove(nil) }程式執行後,控制台輸出如下: 擴充知識:list刪除所有元素
借助list包提供的API,list用起來確實挺方便,但是在使用過程中,如果不注意就會遇到一些難以發現的坑,導致程序結果不是預想的那樣。這裡要說的坑是透過for迴圈來遍歷list,並刪除所有元素時會遇到的問題。例如,下面這個範例程式建立了一個list,並依序將0-3存入,然後透過for循環遍歷list刪除所有元素:
package main import ( "container/list" "fmt" ) func main() { l := list.New() l.PushBack(0) l.PushBack(1) l.PushBack(2) l.PushBack(3) fmt.Println("original list:") prtList(l) fmt.Println("deleted list:") for e := l.Front(); e != nil; e = e.Next() { l.Remove(e) } prtList(l) } func prtList(l *list.List) { for e := l.Front(); e != nil; e = e.Next() { fmt.Printf("%v ", e.Value) } fmt.Printf("n") }
執行程式輸出如下:
original list: 0 1 2 3 deleted list: 1 2 3
從輸出可以知道,list中的元素並沒有被完全刪除,僅刪除了第一個元素0,和最初設想不一樣,按照go的使用習慣,遍歷一個list並刪除所有元素寫法應該如下:
for e := l.Front(); e != nil; e = e.Next() { l.Remove(e) }
但是根據上面範例程式碼的輸出,這樣刪除list所有元素是無效的,那麼問題出在哪裡呢?由for迴圈的機制可以知道,既然刪除了第一個元素,沒有刪除第二個元素,肯定是第二次循環的條件無效,才導致循環退出,即執行完下面語句後:
l.Remove(e)
e應該是nil,所以循環退出。在for迴圈中的l.Remove(e)語句前加入列印語句驗證,例如新增如下語句:
fmt.Println("delete a element from list")
執行程式輸出如下:
original list: 0 1 2 3 deleted list: delete a element from list 1 2 3
可以看到,確實只循環了一次,循環就結束了。即執行完語句l.Remove(e)後,e等於e.Next(),因為e.Next()為nil,導致e為nil,循環退出。為什麼e.Next()會是nil呢?透過查看go list原始碼,如下所示:// 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
}
// Remove removes e from l if e is an element of list l.
// It returns the element value e.Value.
func (l *List) Remove(e *Element) interface{} {
if e.list == l {
// if e.list == l, l must have been initialized when e was inserted
// in l or l == nil (e is a zero Element) and l.remove will crash
l.remove(e)
}
return e.Value
}
由原始碼中可以看到,當執行l.Remove(e)時,會在內部呼叫l.remove(e)方法刪除元素e,為了避免記憶體洩漏,會將e.next和e.prev賦值為nil,這就是問題根源。 修正程式如下:
package main import ( "container/list" "fmt" ) func main() { l := list.New() l.PushBack(0) l.PushBack(1) l.PushBack(2) l.PushBack(3) fmt.Println("original list:") prtList(l) fmt.Println("deleted list:") var next *list.Element for e := l.Front(); e != nil; e = next { next = e.Next() l.Remove(e) } prtList(l) } func prtList(l *list.List) { for e := l.Front(); e != nil; e = e.Next() { fmt.Printf("%v ", e.Value) } fmt.Printf("n") }###執行程式輸出如下:###
original list: 0 1 2 3 deleted list:###可以看見,list中的所有元素已經正確刪除。 ######【相關推薦:###Go影片教學###、###程式設計教學###】###
以上是go語言中list怎麼刪除元素的詳細內容。更多資訊請關注PHP中文網其他相關文章!