I need to implement a server in Golang. I'm using the net package for this purpose but I do not understand how to break out from the accept loop gracefully.
So looking at the example from the net package:
ln, err := net.Listen("tcp", ":8080")
if err != nil {
// handle error
}
for {
conn, err := ln.Accept()
if err != nil {
// handle error
}
go handleConnection(conn)
}
I want to do something more along the lines of:
for {
select {
case <-done:
break
case conn, err := <-ln.Accept():
if err != nil {
break
}
...
}
I other words, I want to be able to terminate the program gracefully somehow.
The best practice, with any service, to ensure a clean shutdown is to ensure each part of the service supports cancelation. Adding context.Context support is the recommended way to achieve this.
So first, ensure your net.Listener does not hang on rogue client connection. So to add context.Context support:
var lc net.ListenConfig
ln, err := lc.Listen(ctx, "tcp", ":8080")
Canceling ctx will break any rogue client connection here that may be blocking during handshake.
EDIT:
To ensure we can break out of the Listen() call while it is blocked waiting, one can leverage the same ctx state and (as noted in a previous, now deleted, answer) close the connection when a cancelation event is detected:
go func() {
<-ctx.Done()
log.Println("shutting service down...")
ln.Close()
}()
Working example: https://play.golang.org/p/LO1XS4jBQ02
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With