如何在Goroutine中记录服务器初始化成功的日志?
解决http.ListenAndServe启动成功日志无法执行的问题
http.ListenAndServe在无错误时会一直阻塞执行,导致goroutine里的成功日志代码永远跑不到;如果直接在goroutine外打日志,又可能在服务还没真正启动(比如端口占用的错误还没触发)就提前输出,日志不准确。
可行的解决方案
我们可以拆分http.ListenAndServe的逻辑——它本质是先监听端口、再启动服务的封装。我们可以手动完成监听步骤,确认端口监听成功后再记录日志,最后启动服务:
package main import ( "fmt" "net" "net/http" ) func main() { addr := "127.0.0.1:9090" server := &http.Server{Addr: addr, Handler: nil} // 先尝试监听目标端口,确认端口可用 listener, err := net.Listen("tcp", addr) if err != nil { fmt.Println("端口监听失败:", err) return } // 走到这一步说明端口已成功监听,服务可以正常启动,此时记录成功日志 fmt.Println("服务启动成功,正在监听", addr) // 在goroutine中启动服务处理请求 go func() { err := server.Serve(listener) // 排除服务器正常关闭的错误 if err != nil && err != http.ErrServerClosed { fmt.Println("服务运行异常:", err) } }() // 阻塞主goroutine,避免进程退出 select{} }
方案说明
- 先通过
net.Listen尝试绑定端口,这一步如果成功,就说明服务具备启动条件,此时输出启动成功日志完全准确 - 再在goroutine中调用
server.Serve处理请求,即使它后续阻塞,也不会影响已经输出的成功日志 - 主goroutine用
select{}保持阻塞,避免进程提前退出
内容的提问来源于stack exchange,提问作者mirko sailorm
相关产品推荐
相关产品推荐

