共计 1387 个字符,预计需要花费 4 分钟才能阅读完成。
在 go 语言里启动一个 http 服务非常简单,只须要一行代码 http.ListenAndServe()
就能够搞定,这个办法会始终阻塞着直到过程敞开,如果这个时候来了些非凡的需要比方:
- 监听服务启动
- 手动敞开服务
- 监听服务敞开
在 go 中应该怎么实现呢?上面来一一举例。
监听服务启动
办法一(举荐)
将 Listen
步骤拆分进去,先监听端口,再绑定到 server
上,代码示例:
l, _ := net.Listen("tcp", ":8080") | |
// 服务启动胜利,进行初始化 | |
doInit() | |
// 绑定到 server 上 | |
http.Serve(l, nil) |
办法二
通过一个 协程
去轮询监听服务启动状态,代码示例:
go func() { | |
for {if _, err := net.Dial("tcp", "127.0.0.1:8080"); err == nil { | |
// 服务启动胜利,进行初始化 | |
doInit() | |
// 退出协程 | |
break | |
} | |
// 每隔一秒查看一次服务是否启动胜利 | |
time.Sleep(time.Second) | |
} | |
}() | |
http.ListenAndServe(":8080", nil) |
手动敞开服务
优雅敞开(举荐)
在 http
包中并没有裸露服务的敞开办法,通过 http.ListenAndServe()
办法启动的 http 服务默认帮咱们创立了一个 *http.Server
对象,源码如下:
func ListenAndServe(addr string, handler Handler) error {server := &Server{Addr: addr, Handler: handler} | |
return server.ListenAndServe()} |
实际上在 *http.Server
中是有提供 Shutdown
办法的,所以咱们只须要手动结构一个 *http.Server
对象,就能够进行优雅敞开了,代码示例:
srv := &http.Server{Addr: ":8080"} | |
go func(){ | |
// 10 秒之后敞开服务 | |
time.Sleep(time.Second * 10) | |
srv.Shutdown(context.TODO()) | |
}() | |
// 启动服务 | |
srv.ListenAndServe() |
强制敞开
强制敞开和下面步骤是一样的,只是调用的办法换成了srv.Close()
,这会导致所有的申请立刻中断,所以须要特地留神。
监听服务敞开
当咱们手动将服务敞开之后,srv.ListenAndServe()
办法就会立刻返回,这里须要留神的是该办法会返回一个 error
,当然这个error
是一个非凡的 error http.ErrServerClosed
,帮忙咱们辨别是否为失常的服务敞开,所以须要对它非凡解决下,代码示例:
if err := server.ListenAndServe(); err != nil { | |
// 服务敞开,进行解决 | |
doShutdown() | |
if err != http.ErrServerClosed{ | |
// 异样宕机,打印错误信息 | |
log.Fatal(err) | |
} | |
} |
参考资料
- how-to-stop-http-listenandserve
- go-how-can-i-start-the-browser-after-the-server-started-listening
我是 MonkeyWie,欢送扫码???????? 关注!不定期在公众号中分享
JAVA
、Golang
、前端
、docker
、k8s
等干货常识。
正文完