为什么goroutine阻止这个http服务器的主要功能?

时间:2017-05-09 04:19:47

标签: go

我想设置一个http服务器,httprouter在两个端口88888080上侦听,就像下面的代码一样。

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)) }()

它在80808888都能正常运作。那么为什么呢?这是关于closure还是别的什么?

2 个答案:

答案 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))
}