Home  >  Article  >  Backend Development  >  Unable to receive last value sent along channel in main goroutine Golang

Unable to receive last value sent along channel in main goroutine Golang

WBOY
WBOYforward
2024-02-09 11:33:09495browse

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

The main goroutine in Golang cannot receive the last value sent along the channel. This is because when the channel is closed, the goroutine cannot receive new values ​​again. Instead, it blocks on the receive operation until all values ​​in the channel have been received. This is a design choice in Golang to avoid possible deadlock situations during receive operations. Therefore, we need to pay special attention to this when writing Golang programs to avoid potential problems and errors.

Question content

Given TCP port scanner in golang. 2 implementations, the first is mine and the second is from the golang book. Assume the second one is 100% feasible, as many readers have tested before. But it seems that both have the same problem: the last value sent in the result channel cannot be received in the main coroutine, it gets stuck waiting infinitely for the value from the channel, despite the The value is actually sent. Some observations: When the number of ports is less than 21, it works as expected; when the amount exceeds 1000, the amount not received increases to around 10. I do not understand why.

Implementation in the book

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)

}

Workaround

This issue has been solved by adding a timeout to 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
    }
}

The above is the detailed content of Unable to receive last value sent along channel in main goroutine Golang. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete