Heim >Backend-Entwicklung >Golang >Der letzte über den Kanal in der Haupt-Goroutine Golang gesendete Wert konnte nicht empfangen werden
Der letzte über den Kanal in der Haupt-Goroutine Golang gesendete Wert kann nicht empfangen werden. Dies liegt daran, dass die Goroutine beim Schließen des Kanals keine neuen Werte mehr empfangen kann. Stattdessen blockiert es den Empfangsvorgang, bis alle Werte im Kanal empfangen wurden. Dies ist eine Entwurfsentscheidung in Golang, um mögliche Deadlock-Situationen während Empfangsvorgängen zu vermeiden. Daher müssen wir beim Schreiben von Golang-Programmen besonders darauf achten, um mögliche Probleme und Fehler zu vermeiden.
Gegebener TCP-Port-Scanner in Golang. 2 Implementierungen, die erste stammt von mir und die zweite stammt aus dem Golang-Buch. Gehen Sie davon aus, dass die zweite Variante zu 100 % machbar ist, wie viele Leser bereits getestet haben. Aber es scheint, dass beide das gleiche Problem haben: Der letzte im Ergebniskanal gesendete Wert kann in der Hauptkoroutine nicht empfangen werden, sie bleibt hängen und wartet endlos auf den Wert vom Kanal, obwohl der Wert tatsächlich gesendet wird. Einige Beobachtungen: Wenn die Anzahl der Ports weniger als 21 beträgt, funktioniert es wie erwartet; wenn die Anzahl 1000 übersteigt, erhöht sich die nicht empfangene Menge auf etwa 10. Ich verstehe nicht warum.
Umsetzung im Buch
func worker(ports, results chan int) { for p := range ports { address := fmt.Sprintf("scanme.nmap.org:%d", p) conn, err := net.Dial("tcp", address) if err != nil { results <- 0 fmt.Println("sent", p) continue } conn.Close() results <- p fmt.Println("sent", p) } } func main() { ports := make(chan int, 100) results := make(chan int) var openports []int for i := 0; i < cap(ports); i++ { go worker(ports, results) } go func() { for i := 1; i <= 50; i++ { ports <- i } }() for i := 0; i < 50; i++ { port := <-results // after 49 it gets stuck infinitely, never proceed further fmt.Println("received", port, i) if port != 0 { openports = append(openports, port) } } close(ports) close(results) sort.Ints(openports) fmt.Println(openports) }
Dieses Problem wurde durch Hinzufügen einer Zeitüberschreitung zu net.Dialer gelöst
func worker(ports, results chan int) { dialer := net.Dialer{Timeout: time.Second} for p := range ports { address := fmt.Sprintf("scanme.nmap.org:%d", p) conn, err := dialer.Dial("tcp", address) if err != nil { results <- 0 continue } conn.Close() results <- p } }
Das obige ist der detaillierte Inhalt vonDer letzte über den Kanal in der Haupt-Goroutine Golang gesendete Wert konnte nicht empfangen werden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!