[英]Why this goroutine leaks?
我正在閱讀“ Go中的並發性”,並且發現了goroutine泄漏的以下示例:
func main() {
var wg sync.WaitGroup
doWork := func(strings <-chan string) <-chan interface{} {
completed := make(chan interface{})
go func() {
defer fmt.Println("doWork exited.")
defer close(completed)
defer wg.Done()
fmt.Println("a")
for s := range strings {
fmt.Println(s)
}
fmt.Println("b")
}()
return completed
}
wg.Add(1)
doWork(nil)
fmt.Println("Waiting")
wg.Wait()
fmt.Println("Done.")
}
strings
通道將永遠不會寫入任何字符串,並且包含doWork
的goroutine將在進程的整個生命周期內保留在內存中。
我不明白-為什么?
我如何理解此代碼:
由於strings
為nil
range
-loop只是跳過了。 作為任何超過nil
范圍:
slice := []int{10, 20, 30, 40, 50} slice = nil for i := range slice { fmt.Println(i) } fmt.Println("Done")
fmt.Println("doWork exited.")
將被執行
close(completed)
將被執行 但我看到它像那樣工作。 為什么呢
由於字符串為零,因此僅跳過了范圍循環。
這個假設是不正確的。 在Go中,從nil
通道讀取將始終受阻。 這是在語言規范中定義的(感謝@peterSO挖掘出鏈接):
從零信道接收將永遠阻止。
Go Design Patterns博客上還有一篇文章 ,進一步闡述了這種行為,並重點介紹了一些有用的情況。
無論如何,可以通過一個最小的示例( Playground )輕松地重現此行為:
func main() {
var s chan string
<- s
}
該程序將永遠不會完成(在操場上, all goroutines are asleep - deadlock
將進入all goroutines are asleep - deadlock
,這將使其崩潰all goroutines are asleep - deadlock
)。
因為從nil通道(在您的示例中為strings
)讀取將被阻塞(永遠,因為無法將任何內容寫入nil通道),所以doWork
goroutine將永遠不會完成,因此會泄漏。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.