本文介绍如何用 `sync.waitgroup` 替代阻塞式 channel 信号机制,安全、可靠地等待所有爬虫 goroutine 完成,避免死锁和竞态问题。
在构建并发 Web 爬虫时,一个常见误区是依赖“单次发送的 done channel”(如 chan bool)来通知主 goroutine 任务结束。正如原始代码所示:当 queue 函数在无待处理任务且 currentJobs == 0 时尝试向 stop
根本问题在于:channel 信号无法表达“所有工作者已彻底退出”的语义;它只是一次性通信,而爬虫任务存在生产者-消费者链路(queue → workers → queue),状态分散在多个 goroutine 中。此时,sync.WaitGroup 是更合适、更符合 Go 并发哲学的解决方案。
WaitGroup 通过原子计数跟踪活跃 goroutine 数量,天然支持“工作启动即注册、工作完成即注销、主协程阻塞等待归零”的生命周期管理。以下是重构后的核心实践: