Webcrawler in Go

Ich versuche, in Go einen Webcrawler zu erstellen, in dem ich die maximale Anzahl gleichzeitiger Worker angeben möchte. Sie werden alle funktionieren, solange in der Warteschlange ein Link zum Erkunden vorhanden ist. Wenn die Warteschlange weniger Elemente als Worker enthält, sollten Worker das Fenster schließen, aber den Vorgang fortsetzen, falls mehr Links gefunden werden.

Der Code, den ich ausprobiert habe, ist

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)
}

Link zum Spielplatz

Dies scheint zu funktionieren, aber es gibt einen Haken: Ich muss die Warteschlange mit mehr als einem Element füllen, wenn ich anfange. Ich möchte, dass es von einer (einzelnen) Startseite ausgeht (in meinem Beispielqueue <- 0) und vergrößern / verkleinern Sie dann den Arbeitspool dynamisch.

Meine Fragen sind:

wie kann ich verhalten bekommen?

warum ist aufschiebenwg.Done() Deadlock verursachen? Es ist normal zuwg.Done() die Funktion, wenn es tatsächlich abgeschlossen ist? Ich denke das ohne dasdefer Die Goroutine wartet nicht darauf, dass der andere Teil fertig ist (was im Beispiel des Parsens von HTML in der Praxis länger dauern könnte).

Antworten auf die Frage(2)

Ihre Antwort auf die Frage