我想设置一个http服务器,httprouter在两个端口8888
和8080
上侦听,就像下面的代码一样。
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!\n")
}
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))
}
但是它无法正常工作,我的服务器只能在8080
上听。如果我做了一些改动:
go func() { log.Fatal(http.ListenAndServe(":8080", router)) }()
它在8080
和8888
都能正常运作。那么为什么呢?这是关于closure
还是别的什么?
答案 0 :(得分:6)
在调用goroutine
中照常评估函数值和参数
- Go language spec, "Go statements"。
您正在为log.Fatal
调用创建goroutine,但参数预先评估log.Fatal
在主goroutine中。 Fatal
的参数是http.ListenAndServe
的返回值。因此,在 ListenAndServe
返回之后,新的goroutine才会启动。
答案 1 :(得分:1)
试试这个。
第一个http.ListenAndServe
语句应放在函数内。这是如何将语句块作为goroutine执行的示例之一,只需将其包装在函数中然后调用它。
保持第二个听,因为它需要阻止。
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))
}