I want to setup a http server with httprouter listening on two ports 8888
and 8080
just like the code below.
package main
import (
"fmt"
"github.com/julienschmidt/httprouter"
"log"
"net/http"
)
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprint(w, "Welcome!
")
}
func main() {
router := httprouter.New()
router.GET("/", Index)
fmt.Println("listen on 8080")
// this is where blocked
go log.Fatal(http.ListenAndServe(":8080", router))
fmt.Println("listen on 8888")
log.Fatal(http.ListenAndServe(":8888", router))
}
But it doesn't work properly,my server only listen on 8080
.If I make some change:
go func() { log.Fatal(http.ListenAndServe(":8080", router)) }()
It works finely both on 8080
and 8888
.So why? It's about closure
or something else?
The function value and parameters are evaluated as usual in the calling goroutine
— Go language spec, "Go statements".
You're creating a goroutine for the call to log.Fatal
, but the arguments to log.Fatal
are evaluated beforehand, in the main goroutine. And Fatal
's argument is the return value of http.ListenAndServe
. So the new goroutine doesn't start until after ListenAndServe
returns.
Try this.
The first http.ListenAndServe
statement should be placed inside function. That is one of the example how to execute block of statements as goroutine, just wrap it inside a function then call it.
Keep the second listen as it is, it's need to be blocking.
func main() {
router := httprouter.New()
router.GET("/", Index)
go func() {
fmt.Println("listen on 8080")
log.Fatal(http.ListenAndServe(":8080", router))
}()
fmt.Println("listen on 8888")
log.Fatal(http.ListenAndServe(":8888", router))
}