以下是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
}
答案 0 :(得分:4)
问题是sizes
不是缓冲的chan
,因此在需要读取sizes
之前,只有一个匿名goroutine可以实际完成。这使得wg.Wait()
永远等待(因为下一个goroutine在sizes <-
上阻止,并且可以defer wg.Done()
)和死锁。
通过将近距离投射到一个单独的goroutine中,只要它准备好就可以关闭sizes
chan,然后在sizes
之间进行处理。最终,这是一个伟大的使用goroutine - 火和忘记关闭!
要使此代码在没有更接近goroutine的情况下工作,您只需将sizes
初始化为缓冲的chan,其缓冲区为&gt; = 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
和....是的,基本上您只是重新开始 - 写完整个功能。