go 언어 구덩이 list 모든 요소 삭제
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 의 모든 요소 가 올 바 르 게 삭제 되 었 음 을 볼 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
어떻게 한 줄 씩 파일 을 읽 습 니까?텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.