我正在尝试在Go中启动HTTP服务器,并且当服务器启动时,应该打印一条消息,如果出现错误,应该打印一条错误消息。
给出以下代码:
const (
HTTPServerPort = ":4000"
)
func main() {
var httpServerError = make(chan error)
var waitGroup sync.WaitGroup
setupHTTPHandlers()
waitGroup.Add(1)
go func() {
defer waitGroup.Done()
httpServerError <- http.ListenAndServe(HTTPServerPort, nil)
}()
if <-httpServerError != nil {
fmt.Println("The Logging API service could not be started.", <-httpServerError)
} else {
fmt.Println("Logging API Service running @ http://localhost" + HTTPServerPort)
}
waitGroup.Wait()
}
当我启动应用程序时,我看不到要打印到控制台的任何内容:
Logging API Service running @ http://localhost:4000
当我将端口更改为无效端口时,以下输出将输出到控制台:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
...app.go:45 +0x107
exit status 2
有人能指出我正确的方向,以便让我知道我在执行此操作时做错了什么吗?
答案 0 :(得分:2)
除非更改代码中的逻辑或分别使用Listen
和Serve
,否则您将无法执行此操作。因为ListenAndServe
是一个阻塞函数。如果发生意外情况,它将返回一个错误。如果不是这样,它将继续阻止服务器运行。启动服务器时都不会触发任何事件。
然后让我们分别运行Listen
和Serve
。
l, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
// Signal that server is open for business.
if err := http.Serve(l, rootHandler); err != nil {
// handle error
}
请参见https://stackoverflow.com/a/44598343/4792552。
P.S。 net.Listen
不会阻止,因为它在后台运行。换句话说,它只是生成OS级别的套接字连接,并向您返回其详细信息/ ID。因此,您可以使用该ID将订单代理到该套接字。
答案 1 :(得分:1)
问题是您的if语句将始终从httpServerError
通道读取。但是,只有当服务器发生故障时,才会向其中写入内容。
尝试使用select
语句:
select{
case err := <-httpServerError
fmt.Println("The Logging API service could not be started.", err)
default:
fmt.Println("Logging API Service running @ http://localhost" + HTTPServerPort
}
如果频道上没有任何内容,将运行default
情况。
请注意,您的示例不会两次从通道读取该消息。从通道读取值后,它就消失了。把它当成队列。