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


Still fully getting my head around goroutines and channels, so I might be doing something obviously wrong. I have a service that runs a websocket server and public route used to upgrade clients from https to wss. I am trying to attach some tear-down code for one of the routines, but the second go call seems to block the main function’s execution. I reach Println 5 on the console on boot up. The rest of my program is happily working. I just can’t kill it with a ctrl+C (nor does it do it’s required tear down after a manual shut down).

Here’s the relevant code (the complete main file minus the streamAddr var and the imports):

func main() {

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

    hub := socktools.NewHub()
    go hub.Run()

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

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


    select {
    case <-interrupt:
        fmt.Println("Interrupt heard...")
        fmt.Println("Ending main function")

Why is go log.Fatal(http.ListenAndServe(*streamAddr, nil)) blocking? I thought that the go keyword instantly made it asynchronous? Am I using it wrong here?


You are essentially calling go log.Fatal(variable), so the async call is log.Fatal, but it has to know what variable is at that moment, so it first has to call http.ListenAndServe to see what it returns. But http.ListenAndServe blocks.

You need to do:

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

Answered By – dave

Answer Checked By – Gilberto Lyons (GoLangFix Admin)

Leave a Reply

Your email address will not be published.