我正在研究并发的Go库,偶然发现了goroutine之间两种相似的同步模式,其结果相似:
使用等待组
var wg sync.WaitGroup func main() { words := []string{ "foo", "bar", "baz" } for _, word := range words { wg.Add(1) go func(word string) { time.Sleep(1 * time.Second) defer wg.Done() fmt.Println(word) }(word) } // do concurrent things here // blocks/waits for waitgroup wg.Wait() }
使用频道
func main() { words = []string{ "foo", "bar", "baz" } done := make(chan bool) defer close(done) for _, word := range words { go func(word string) { time.Sleep(1 * time.Second) fmt.Println(word) done <- true }(word) } // Do concurrent things here // This blocks and waits for signal from channel <-done }
有人告诉我,sync.WaitGroup它的性能要好一些,而且我已经看到它被普遍使用。但是,我发现频道更惯用了。sync.WaitGroup通过渠道使用的真正优势是什么?和/或更好的情况又可能是什么情况?
sync.WaitGroup
独立于第二个示例的正确性(如注释中所述,您没有按照自己的想法进行操作,但是很容易修复),我倾向于认为第一个示例更容易掌握。
现在,我什至不会说渠道更加惯用。通道是Go语言的一种签名功能,并不意味着在任何可能的情况下使用它们都是惯用的。Go的惯用用法是使用最简单,最容易理解的解决方案:在这里,WaitGroup传达含义(您的主要职能是Wait完成工作)和机制(工作人员在工作时通知Done)。
WaitGroup
Wait
Done
除非您的情况非常特殊,否则我不建议您在此使用渠道解决方案。