Go language Pit list Delete all elements

Source: Internet
Author: User
Tags python list
This is a creation in Article, where the information may have evolved or changed.

Go provides a list package, like a python list, that can store any type of data and provide the appropriate APIs, as follows:

  Type Element func (e *element) Next () *element func (e *element) Prev () *elementtype 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 *lis T) pushfrontlist (other *list) func (L *list) Remove (e *element) interface{}  

It is really handy to use the api,list provided with the list package, but in the process of using it, if you are not careful you will encounter some pits that are difficult to spot, resulting in a program that is not as expected. The pit here is the problem of traversing the list through a for loop and removing all elements. For example, the following example program creates a list, stores 0-3 sequentially, and then iterates through the list with a for loop to delete all the elements:

package mainimport (    "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")}

Run the program output as follows:

original list:0 1 2 3 deleted list:1 2 3

From the output you can know that the elements in the list are not completely deleted, only the first element 0 is deleted, and the original idea is not the same, according to the use of Go habits, walk a list and delete all the elements should be written as follows:

for e := l.Front(); e != nil; e = e.Next() {    l.Remove(e)}

But according to the output of the example code above, it is not valid to delete all the elements of list, so what is the problem? The mechanism of the For loop knows that since the first element has been deleted, the second element has not been deleted, and the condition of the second loop must be invalid to cause the loop to exit, after executing the following statement:

l.Remove(e)

E should be nil, so the loop exits. The L in the for loop. Remove (e) statement before adding a print statement validation, such as adding the following statement:

fmt.Println("delete a element from list")

Run the program output as follows:

original list:0 1 2 3 deleted list:delete a element from list1 2 3

As you can see, it's really just a loop, and the loop ends. That is, when you finish executing the statement L. After Remove (e), E is equal to E. Next (), because E. Next () is nil, causing E to nil and the loop to exit. Why E. Next () will be nil? By looking at the Go List source, as shown below:

// 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}

By the source can be seen when executing L. Remove (e), the L.remove (e) method is called internally to delete element E, in order to avoid a memory leak, the E.next and E.prev are assigned to nil, which is the source of the problem.

The correct procedure is as follows:

package mainimport (    "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")}

Run the program output as follows:

original list:0 1 2 3 deleted list:

As you can see, all the elements in the list have been deleted correctly.

This recommendation: simple logic


Simple logic.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.