Problem:
In der Go-Tour-Übung #71: Die Verwendung von go run 71_hang.go nogood führt dazu, dass das Programm auf unbestimmte Zeit läuft, während go run 71_hang.go ok wie folgt funktioniert erwartet. Der einzige Unterschied besteht im Hinzufügen von fmt.Print("") im Standardfall der Select-Anweisung.
Erklärung:
Eine Standardanweisung in einer Select-Anweisung ändert sich das Verhalten der Aussage. Ohne Vorgabe wählen Sie Blöcke aus, bis Nachrichten auf den Kanälen vorhanden sind. Bei einer Standardeinstellung führt select die Standardanweisung jedes Mal aus, wenn von den Kanälen nichts zu lesen ist.
Im Originalcode erstellt die Standardanweisung eine Endlosschleife. Da der Scheduler keine anderen Goroutinen einplanen kann, läuft das Programm auf unbestimmte Zeit.
Lösung 1:
Entfernen Sie die Standardanweisung und verwenden Sie eine nicht blockierende Auswahl:
for { select { case todo := <-toDoList: if todo.depth > 0 && !visited[todo.url] { crawling++ visited[todo.url] = true go crawl(todo, fetcher, toDoList, doneCrawling) } case <-doneCrawling: crawling-- } if crawling == 0 { break } }
Lösung 2:
Behalten die Standardanweisung, aber stellen Sie sicher, dass die Goroutine nachgibt. Eine Möglichkeit, dies zu erreichen, ist die Verwendung von GOMAXPROCS=2, wodurch der Scheduler mehrere Kerne verwenden kann.
Zusätzlicher Hinweis:
Goroutinen werden kooperativ geplant. Select ist ein Punkt, an dem eine Goroutine nachgeben sollte. Im gegebenen Beispiel ist jedoch der Grund, warum „select“ ohne die Anweisung „fmt.Print()“ nicht ausgibt, nicht vollständig geklärt und erfordert weitere Untersuchungen.
Das obige ist der detaillierte Inhalt vonWarum bleibt eine Go „select'-Anweisung ohne einen „default'-Fall hängen und wie kann das behoben werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!