我正在尝试在 Go 中构建一个网络爬虫,我想在其中指定并发工作人员的最大数量。只要队列中有可供探索的链接,它们都会工作。当队列的元素少于工作人员时,工作人员应该大声喊叫,但如果找到更多链接,则继续。
我试过的代码是
const max_workers = 6
// simulating links with int
func crawl(wg *sync.WaitGroup, queue chan int) {
for element := range queue {
wg.Done() // why is defer here causing a deadlock?
fmt.Println("adding 2 new elements ")
if element%2 == 0 {
wg.Add(2)
queue <- (element*100 + 11)
queue <- (element*100 + 33)
}
}
}
func main() {
var wg sync.WaitGroup
queue := make(chan int, 10)
queue <- 0
queue <- 1
queue <- 2
queue <- 3
var min int
if (len(queue) < max_workers) {
min = len(queue)
} else {
min = max_workers
}
for i := 0; i < min; i++ {
wg.Add(1)
go crawl(&wg, queue)
}
wg.Wait()
close(queue)
}
链接到游乐场
这似乎有效,但有一个问题:当我开始时,我必须用多个元素填充队列。我希望它从(单个)种子页面(在我的示例中queue <- 0)开始,然后动态地扩大/缩小工作池。
我的问题是:
我怎样才能获得行为?
为什么 defer 会wg.Done()
导致死锁?wg.Done()
实际完成后功能正常吗?我认为没有defer
goroutine 不会等待另一部分完成(在解析 HTML 的实际工作示例中可能需要更长的时间)。
芜湖不芜
相关分类