[英]Sync.WaitGroup, why closer in a goroutine
以下是Go編程手冊中的示例代碼。 我不明白為什么閉合器需要自己的goroutine。 我試圖將更近的物體移入主殼體,但它崩潰了。 有人可以解釋為什么閉合器需要放在單獨的goroutine中?
謝謝!
func makeThumbnails(filenames <-chan string, result chan<- int64) int64 {
sizes := make(chan int64)
var wg sync.WaitGroup
for f := range filenames {
wg.Add(1)
go func(f string) {
defer wg.Done()
sizes <- int64(len(f))
}(f)
}
// **closer**, why this guy needs to be in a goroutine???
go func() {
wg.Wait()
close(sizes)
}()
var total int64
for size := range sizes {
total += size
}
result <- total
return total
}
問題是, sizes
是不是一個緩沖chan
,所以只能匿名夠程前能實際完成的一個sizes
需要被讀取。 這使wg.Wait()
永遠等待(因為下一個goroutine在sizes <-
上阻塞,並且不能defer wg.Done()
)和死鎖。
通過將關閉器投入一個單獨的goroutine中,它可以在准備好關閉sizes
chan時就關閉它,並在中間的sizes
之間進行處理。 最終,這是goroutine的絕佳用法-開火,然后忘記關閉!
為了使此代碼在沒有更緊密的goroutine的情況下工作,您可以簡單地將sizes
初始化為緩沖區chan,其緩沖區> = filenames
的長度。
func makeThumbnails(filenames <-chan string, result chan<- int64) int64 {
sizes := make(chan int64, 10) // buffered channel, now!
// if filenames sends more than 10 strings, though, we're in trouble!!
var wg sync.WaitGroup
for f := range filenames {
wg.Add(1)
go func(f string) {
defer wg.Done()
sizes <- int64(len(f))
}(f)
}
// **closer**, this guy doesn't need to be a goroutine!!
wg.Wait()
close(sizes)
var total int64
for size := range sizes {
total += size
}
result <- total
return total
}
但是,由於filenames
的長度在運行時是未知的,因此無法輕松做到這一點。 你必須通過閱讀filenames
,將其存儲到一個切片,然后初始化大小和for
在range filenamesSlice
和....是啊基本上你只是重新寫在該點的整體功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.