Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Tidak dapat menerima nilai terakhir yang dihantar sepanjang saluran dalam goroutine utama Golang

Tidak dapat menerima nilai terakhir yang dihantar sepanjang saluran dalam goroutine utama Golang

WBOY
WBOYke hadapan
2024-02-09 11:33:09497semak imbas

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

Tidak dapat menerima nilai terakhir yang dihantar sepanjang saluran dalam goroutine utama Golang. Ini kerana apabila saluran ditutup, goroutine tidak boleh menerima nilai baru lagi. Sebaliknya, ia menyekat operasi terima sehingga semua nilai dalam saluran telah diterima. Ini adalah pilihan reka bentuk di Golang untuk mengelakkan kemungkinan situasi kebuntuan semasa operasi penerimaan. Oleh itu, kita perlu memberi perhatian khusus kepada perkara ini semasa menulis program Golang untuk mengelakkan masalah dan ralat yang berpotensi.

Kandungan soalan

Diberi pengimbas port TCP dalam golang. 2 perlaksanaan, pertama saya dan kedua dari buku golang. Anggap yang kedua adalah 100% boleh dilaksanakan, kerana ramai pembaca telah menguji sebelum ini. Tetapi nampaknya kedua-duanya mempunyai masalah yang sama: nilai terakhir yang dihantar dalam saluran hasil tidak boleh diterima dalam coroutine utama, ia tersekat menunggu tanpa terhingga nilai dari saluran, walaupun nilai sebenarnya dihantar. Beberapa pemerhatian: Apabila bilangan port kurang daripada 21, ia berfungsi seperti yang dijangkakan apabila jumlah melebihi 1000, jumlah yang tidak diterima meningkat kepada sekitar 10. Saya tidak faham mengapa.

Pelaksanaan dalam buku

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)

}

Penyelesaian

Isu ini telah diselesaikan dengan menambahkan tamat masa pada net.Dialer

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

Atas ialah kandungan terperinci Tidak dapat menerima nilai terakhir yang dihantar sepanjang saluran dalam goroutine utama Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam
Artikel sebelumnya:Goroutine akan tidur lebih awalArtikel seterusnya:Goroutine akan tidur lebih awal