常见的并非模型
经典案例:生成图像缩略图并计算这些缩略图的总大小
func main() { images := []string{ "/Users/xxx/Pictures/avatar/1.jpeg", "/Users/xxx/Pictures/avatar/2.jpeg", "/Users/xxx/Pictures/avatar/3.jpeg", } ch := make(chan string) go func() { defer close(ch) for _, filename := range images { ch <- filename log.Println(filename + " sent .") } }() result := makeThumbnails6(ch) log.Printf("Total size of thumbnails: %d bytes\n", result) } func makeThumbnails6(filenames <-chan string) int64 { sizes := make(chan int64) var wg sync.WaitGroup for f := range filenames { log.Printf("%v receive .", f) wg.Add(1) go func(f string) { defer wg.Done() thumb, err := thumbnail.ImageFile(f) if err != nil { log.Println(err) return } info, _ := os.Stat(thumb) sizes <- info.Size() }(f) } go func() { wg.Wait() close(sizes) }() var total int64 for size := range sizes { total += size } return total }
这里面有几点需要注意的:
1: 闭包的变量: 这里的闭包函数把f 传递进去了,防止改变外部的f
go func(f string) { defer wg.Done() thumb, err := thumbnail.ImageFile(f) if err != nil { log.Println(err) return } info, _ := os.Stat(thumb) sizes <- info.Size() }(f)
2:为什么使用阻塞的size channel?( 外部启动第2个goroutine的时候, makeThumbnails6里面的goroutine执行比较快就结束返回了,关闭了 size channel 怎么办
有一个点很好奇:在makeThumbnails6中如果两次for循环间隔太大,是否导致该函数提前退出。
比如说filenames chan每隔1分钟发送一个消息。但 for f := range filenames 中goroutine只需要半分钟就执行完,看起来会在第二次循环前导致wg.Wait()解除,sizes chan关闭,从而makeThumbnails6未等待filenames chan关闭就返回了)
answer:不会;for f := range filenames 中启动的 goroutine 向 sizes 中发送消息会阻塞(无缓存channel),这样只有循环结束才会开始接收size信息(主goroutine),wg.done之后才会执行,
即wg等待的goroutine数量只会一直增加到最大,然后开始减少,直到wg.wait.
函数中,
makeThumbnails6sizes channel 用于接收处理后的文件大小。由于 sizes 是一个阻塞的 channel,发送操作(sizes <- info.Size())会阻塞直到有 goroutine 从 channel 中接收数据,
这样可以避免在未处理完数据的情况下继续添加更多数据。
3: 这里为什么都是go func() { wg.Wait() close(squared) }() 不能直接在主进程中执行吗?
go func() { wg.Wait() close(sizes) }() var total int64 for size := range sizes { total += size }

浙公网安备 33010602011771号