登录
首页 >  Golang >  Go问答

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

来源:stackoverflow

时间:2024-02-04 22:42:54 443浏览 收藏

在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是Golang学习者,那么本文《Golang中主goroutine无法接收通过通道发送的最后一个值》就很适合你!本篇内容主要包括##content_title##,希望对大家的知识积累有所帮助,助力实战开发!

问题内容

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

理论要掌握,实操不能落!以上关于《Golang中主goroutine无法接收通过通道发送的最后一个值》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>