You can refer to the usage of list packages in golangThis article
However, most elements in the list package that operate on e *Element may cause program crash. The fundamental reason is that e is an Element-type pointer, of course it may also be nil. However, the functions in the list package in golang do not check whether it is nil or not, and default it is not nil for operation. Therefore, in this case, program crash may occur.
1. Give a simple example
Remove() function
package main import ( "container/list" "fmt" ) func main() { l := () (1) (().Value) //1 value := (()) (value) //1 value1 := (()) //panic: runtime error: invalid memory address or nil pointer dereference (value1) }
From the program, we can intuitively see that the program crashes because there is only 1 element in the list, but 2 elements need to be deleted. But if you look at the reasons further, you will get the following results.
The Front() function in golang is implemented as follows
func (l *List) Front() *Element { if == 0 { return nil } return }
It can be seen that after the first deletion. The length of list becomes 0, and at this time (()) is called, where () returns a nil.
Next, let’s look at the implementation of the Remove() function in golang. This function does not determine whether e is nil. Change it directly defaults to non-nil, and directly performs or takes value operations on it.
When e is nil, both operations will cause the program to crash, which is why the above program will crash.
func (l *List) Remove(e *Element) interface{} { if == l { // if == l, l must have been initialized when e was inserted // in l or l == nil (e is a zero Element) and will crash (e) } return }
2.(l *list)PushBackList(other *list)
This function is used to add elements in other lists after l lists.
The basic implementation idea is to take out all elements in other and mount them in the l list in sequence, but there is a problem with the implementation in golang.
The code is as follows
func (l *List) PushBackList(other *List) { () for i, e := (), (); i > 0; i, e = i-1, () { (, ) } }
The specific idea is to first get the length n of other, and then loop n times to remove its element and insert it into l. The problem occurs in the loop n times. If other elements change during this process, for example, some of the elements are deleted, which causes the pointer of e to be nil. At this time, the program will crash if it is used to get the value.
As shown below
package main import ( "container/list" "runtime" ) func main() { (8) l := () ls := () for i := 0; i < 10000; i++ { (i) } go (()) (ls) //invalid memory address or nil pointer dereference }
As shown in the program, let’s talk about adding elements in ls to the l process. If the elements in ls are reduced, the program will crash. The reasons are as analyzed above.
suggestion:
If there are only serial operations on operations with list in golang, you only need to pay attention to checking whether the element pointer is nil to avoid program crash. If the element in list is processed concurrently in the program, it is recommended to write a lock (global lock) to list and then operate it again. Note that read and write locks cannot guarantee the security of the program when processing lists in parallel.
Supplement: golang list link list
Look at the code ~
package main import ( "container/list" "fmt" ) func main() { dataList := () (1) // Insert the end (2) (3) // Insert the header (4) (5) m := (6) m1 := (7,m) // 6 Insert before 7 m2 := (8,m) // Insert after 6 8 // Start traversal from the link list for e := (); e != nil; e = () { () // Print value } ("----------------------------------------") (()) // Remove the head (m2, m) // Before moving m2 (m1, m) (m) // Remove //PushBackList // Insert list //PushFrontList // // Start traversal from the link list for e := (); e != nil; e = () { () // Print value } ("----------------------------------------") // Start traversal from the end of the linked list for e := (); e != nil; e = () { (, " ") } ("----------------------------------------") () // Clear the link list // Start traversal from the link list for e := (); e != nil; e = () { () // Print value } }
Running results:
3
1
2
4
5
7
6
8
----------------------------------------
1
2
4
5
8
7
----------------------------------------
7
8
5
4
2
1
----------------------------------------Process finished with exit code 0
The above is personal experience. I hope you can give you a reference and I hope you can support me more. If there are any mistakes or no complete considerations, I would like to give you advice.