首頁  >  文章  >  後端開發  >  主 goroutine Golang 中無法接收沿通道發送的最後一個值

主 goroutine Golang 中無法接收沿通道發送的最後一個值

WBOY
WBOY轉載
2024-02-09 11:33:09547瀏覽

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

主 goroutine Golang 中無法接收沿著通道發送的最後一個值。這是由於當通道被關閉後,goroutine 無法再次接收新的值。相反,它將一直阻塞在接收操作上,直到通道中的所有值都被接收完畢。這是 Golang 中的設計選擇,旨在避免在接收操作過程中可能出現的死鎖情況。因此,在編寫 Golang 程式時,我們需要特別注意這一點,以避免潛在的問題和錯誤。

問題內容

給定 golang 中的 TCP 連接埠掃描器。 2個實現,第一個是我的,第二個來自golang書。假設第二個是 100% 可行的,正如許多讀者之前測試的那樣。但似乎兩者都有相同的問題:在結果通道中發送的最後一個值無法在主協程中接收,它陷入無限等待來自通道的值,儘管該值實際上已發送。 一些觀察:當端口數量少於 21 個時,它按預期工作;當金額超過1000時,未收到的金額增加到10左右。 我不明白為什麼。

書中的實作

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)

}

解決方法

透過向 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
    }
}

以上是主 goroutine Golang 中無法接收沿通道發送的最後一個值的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除