Webcrawler в Go
Я пытаюсь создать веб-сканер в 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
), а затем динамически увеличивать / уменьшать рабочий пул.
Мои вопросы:
как я могу получить поведение?
почему отложеноwg.Done()
вызывая тупик? Это нормальноwg.Done()
функция, когда она на самом деле завершена? Я думаю, что безdefer
программа не ждет завершения другой части (что может занять больше времени в реальном примере анализа HTML).