listen 和 serve 的 goroutine 阻塞主进程的执行,永远不会达到以下用于通信的 select 状态

Goroutine of listen and serve blocks execution of main process, never reaches following select state used for communication

我仍然完全了解 goroutines 和通道,所以我可能做了一些明显错误的事情。我有一个运行 websocket 服务器和 public 路由的服务,用于将客户端从 https 升级到 wss。我正在尝试为其中一个例程附加一些拆卸代码,但第二个 go 调用似乎阻止了主函数的执行。我在启动时在控制台上到达 Println 5。我程序的其余部分运行得很愉快。我只是不能用 ctrl+C 杀死它(也不需要在手动关闭后将其拆除)。

这是相关代码(完整的主文件减去了 streamAddr 变量和导入):

func main() {
    fmt.Println(1)
    flag.Parse()
    log.SetFlags(0)

    fmt.Println(2)
    interrupt := make(chan os.Signal, 1)
    signal.Notify(interrupt, os.Interrupt)

    fmt.Println(3)
    hub := socktools.NewHub()
    go hub.Run()

    fmt.Println(4)
    http.HandleFunc("/stream", func(w http.ResponseWriter, r *http.Request) {
        socktools.ServeWs(hub, w, r)
    })

    fmt.Println(5)
    go log.Fatal(http.ListenAndServe(*streamAddr, nil))

    fmt.Println(6)

    select {
    case <-interrupt:
        fmt.Println("Interrupt heard...")
        close(hub.KillChan)
        <-hub.KilledChan
        fmt.Println("Ending main function")
        return
   }
}

为什么 go log.Fatal(http.ListenAndServe(*streamAddr, nil)) 阻塞?我以为 go 关键字立即使其异步?我这里是不是用错了?

你实际上是在调用 go log.Fatal(variable),所以异步调用是 log.Fatal,但它必须知道 variable 是什么 那一刻 ,所以它首先必须调用 http.ListenAndServe 来查看它 returns。但是 http.ListenAndServe 块。

您需要做的:

go func() {
    log.Fatal(http.ListenAndServe(*streamAddr, nil))
}()