go 언어 구덩이 list 모든 요소 삭제

22707 단어 글 을 짓다golang
원본 링크:http://reborncodinglife.com/2017/03/30/go-list-remove-all-elements-tips/
go 는 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{}

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

실행 프로그램 출력 은 다음 과 같 습 니 다:
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("
"
) }

실행 프로그램 출력 은 다음 과 같 습 니 다:
original list: 0 1 2 3 deleted list:
list 의 모든 요소 가 올 바 르 게 삭제 되 었 음 을 볼 수 있 습 니 다.

좋은 웹페이지 즐겨찾기