Der letzte über den Kanal in der Haupt-Goroutine Golang gesendete Wert konnte nicht empfangen werden

WBOY
Freigeben: 2024-02-09 11:33:09
nach vorne
527 Leute haben es durchsucht

主 goroutine Golang 中无法接收沿通道发送的最后一个值

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.

Frageninhalt

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)

}
Nach dem Login kopieren

Workaround

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
    }
}
Nach dem Login kopieren

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!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!