Webcrawler en Go
Estoy tratando de construir un rastreador web en Go donde me gustaría especificar el número máximo de trabajadores concurrentes. Todos trabajarán siempre que haya un enlace para explorar en la cola. Cuando la cola tiene menos elementos que los trabajadores, los trabajadores deben gritar, pero reanudar en caso de que se encuentren más enlaces.
El código que probé es
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)
}
Esto parece funcionar, pero hay un problema: tengo que llenar la cola con más de un elemento cuando comienzo. Me gustaría que comenzara desde una página de inicio (única) (en mi ejemploqueue <- 0
) y luego aumentar / reducir el grupo de trabajo de forma dinámica.
Mis preguntas son:
¿Cómo puedo obtener comportamiento?
por qué es diferirwg.Done()
causando un punto muerto? Es normalwg.Done()
la función cuando realmente se completa? Creo que sin eldefer
la rutina no está esperando a que termine la otra parte (lo que podría llevar más tiempo en el ejemplo de trabajo real de analizar HTML).