在Go语言中,主协程(main goroutine)可以使用多种方式来等待其他协程完成其操作。常见的方法是使用通道(channels)和 sync
包中的工具,比如 sync.WaitGroup
。以下是这两种方法的示例:
使用 sync.WaitGroup
sync.WaitGroup
是一个非常方便的工具,用于等待一组协程完成。你可以通过调用 Add
方法来设置要等待的协程数量,并在每个协程完成时调用 Done
方法。最后,使用 Wait
方法来阻塞主协程,直到所有协程都完成。
package mainimport ("fmt""sync""time"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // 确保在函数退出时调用 Donefmt.Printf("Worker %d starting\n", id)time.Sleep(time.Second) // 模拟一些工作fmt.Printf("Worker %d done\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 5; i++ {wg.Add(1) // 增加等待计数go worker(i, &wg)}wg.Wait() // 等待所有协程完成fmt.Println("All workers done.")
}
使用通道(Channels)
另一种方法是使用无缓冲通道。主协程可以创建一个无缓冲通道,并在启动所有协程后将该通道传递给它们。每个协程在完成任务后将一个值发送到该通道。主协程则通过读取通道中的值来等待所有协程完成。
package mainimport ("fmt""time"
)func worker(id int, done chan<- struct{}) {fmt.Printf("Worker %d starting\n", id)time.Sleep(time.Second) // 模拟一些工作fmt.Printf("Worker %d done\n", id)done <- struct{}{} // 发送完成信号
}func main() {const numWorkers = 5done := make(chan struct{}, 0) // 无缓冲通道for i := 1; i <= numWorkers; i++ {go worker(i, done)}// 等待所有协程完成for i := 1; i <= numWorkers; i++ {<-done}fmt.Println("All workers done.")
}
总结
sync.WaitGroup
是一种更简单和直观的方法来等待多个协程完成。- 通道 提供了更灵活的同步机制,但在这种情况下,代码可能会稍微复杂一些。
根据具体需求选择适合的方法,通常 sync.WaitGroup
是更常用的选择,因为它更加简洁和高效。