Golang worker pool没有返回任何结果

jm81lzqq  于 2023-08-01  发布在  Go
关注(0)|答案(1)|浏览(102)

我试图构建一个简单的TCP端口扫描器来练习学习Go中的并发性。我正在关注这个YouTube视频(https://www.youtube.com/watch?v=LvgVSSpwND8),介绍如何使用通道和Goroutines在Go中实现“工人池”。我尝试利用视频中的想法,并实现了TCP扫描器功能,如下所示:

func worker(ports <-chan int, results chan<- string) {
    for p := range ports {
        address := fmt.Sprintf("127.0.0.1:%d", p)
        conn, err := net.Dial("tcp", address)
        if err != nil {
            results <- fmt.Sprintf("Port %d is closed: %s", p, err.Error())
        } else {
            conn.Close()
            results <- fmt.Sprintf("Port %d is open", p)
        }
    }
}

func main() {
    ports := make(chan int, 100)
    results := make(chan string, 100)

    for i := 0; i < cap(ports); i++ {
        go worker(ports, results)
    }

    for j := 1; j <= 65535; j++ {
        ports <- j
    }
    close(ports)

    for k := 1; k <= 65535; k++ {
        fmt.Println(<-results)
    }
    close(results)
}

字符串
我期望它能以随机的顺序慢慢打印出结果,就像YouTube视频中那样。但控制台上没有任何输出。我尝试调试通道,工作函数从端口通道接收端口号,但似乎没有任何东西返回到结果通道。

q9rjltbz

q9rjltbz1#

这是因为你没有在你应该听的时候听结果。
写入ports的for循环将在前100个请求后阻塞,因为这是该通道的大小,并且所有的goroutine将阻塞等待写入results通道,因为没有goroutine从它阅读。
你可以通过监听一个单独的goroutine来修复它:

done:=make(chan struct{})
  go func() {
      defer close(done)
      for k := 1; k <= 65535; k++ {
        fmt.Println(<-results)
      }
      close(results)
  }()

 for j := 1; j <= 65535; j++ {
        ports <- j
    }
 close(ports)
 <-done  // Wait for the reader to finish

字符串

相关问题