1 变量f是被所有的匿名函数值所共享,且会被连续的循环迭代所更新的。
2 。当新的goroutine开始执行字面函数时,for循环可能已经更新了f并且开始了另一轮的迭代或者(更有可能的)已经结束了整个循环,
func makeThumbnails6(filenames <-chan string) int64 {
sizes := make(chan int64)
var wg sync.WaitGroup // number of working goroutines
for f := range filenames {
wg.Add(1)
// worker
go func(f string) {
defer wg.Done()
thumb, err := thumbnail.ImageFile(f)
if err != nil {
log.Println(err)
return
}
info, _ := os.Stat(thumb) // OK to ignore error
sizes <- info.Size()
}(f)
}
// closer
go func() {
wg.Wait()
close(sizes)
}()
var total int64
for size := range sizes {
total += size
}
return total
}
Add必须在worker goroutine开始之前调用 ,我们没办法确定Add是在"closer" goroutine调用Wait之前被调用。
两步操作:wait 后 close,
如果两步操作被放在了main goroutine中,在循环之前,这样的话就永远都不会结束了,
–因为没有range loop 去接受 size:= range sizes 的话 ,done 永远结束不了。
如果在循环之后,那么又变成了不可达的部分,因为没有任何东西去关闭这个channel,这个循环就永远都不会终止。
(当channel没有 数据 总会阻塞这个channel)