我需要在 Golang 中实现一个服务器。我正在使用该net包来实现此目的,但我不明白如何优雅地摆脱循环accept。
所以看一下包中的示例net:
ln, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
for {
conn, err := ln.Accept()
if err != nil {
// handle error
}
go handleConnection(conn)
}
Run Code Online (Sandbox Code Playgroud)
我想做更多的事情:
for {
select {
case <-done:
break
case conn, err := <-ln.Accept():
if err != nil {
break
}
...
}
Run Code Online (Sandbox Code Playgroud)
换句话说,我希望能够以某种方式优雅地终止程序。
对于任何服务,确保干净关闭的最佳实践是确保服务的每个部分都支持取消。添加context.Context支持是实现此目的的推荐方法。
因此,首先,确保您的net.Listener连接不会挂在恶意客户端上。因此要添加context.Context支持:
var lc net.ListenConfig
ln, err := lc.Listen(ctx, "tcp", ":8080")
Run Code Online (Sandbox Code Playgroud)
取消ctx将中断此处可能在握手期间阻塞的任何恶意客户端连接。
编辑:
为了确保我们可以在呼叫阻塞等待时中断呼叫Listen(),可以利用相同的ctx状态并(如之前已删除的答案中所述)在检测到取消事件时关闭连接:
go func() {
<-ctx.Done()
log.Println("shutting service down...")
ln.Close()
}()
Run Code Online (Sandbox Code Playgroud)
工作示例: https: //play.golang.org/p/LO1XS4jBQ02