Graceful shutdown with context.Context
Before the code: what graceful shutdown actually means
Picture a restaurant at closing time. The good waiter does not yell stop and dump plates on the floor. They stop seating new guests, let the people already eating finish, then turn the lights off. That is graceful shutdown for a server. When the operating system sends a stop signal, you want the server to stop accepting new connections, let the writes already in flight finish, then quit. In Go you wire this with a cancellable context and a WaitGroup that knows how many handlers are still running.
Stop accepting, drain, exit
Quiz: Quiz
Loading practice…
Why is this Go's step 9? Because the goroutine + netpoll model already gives us what Python had to engineer with selectors. The remaining production gap is shutdown. When SIGTERM arrives, we want to drain cleanly, not drop connections mid-write.
func main() {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
listener, _ := net.Listen("tcp", addr)
log.Printf("server listening on %s", addr)
var wg sync.WaitGroup
go func() {
for {
conn, err := listener.Accept()
if err != nil { return }
wg.Add(1)
go func(c net.Conn) {
defer wg.Done()
handleConn(ctx, c)
}(conn)
}
}()
<-ctx.Done()
listener.Close()
// wait for handlers with 5s timeout
}signal.NotifyContext turns SIGINT/SIGTERM into a cancelled context. Wait on it in main.
func handleConn(ctx context.Context, conn net.Conn) {
defer conn.Close()
r := bufio.NewReader(conn)
go func() {
<-ctx.Done()
conn.SetReadDeadline(time.Now()) // unblocks Read with timeout error
}()
for {
frame, err := parseRESP(r)
if err != nil { return }
// ... dispatch
select {
case <-ctx.Done(): return // cooperative checkpoint between commands
default:
}
}
}A second goroutine watches ctx.Done() and calls SetReadDeadline(time.Now()) to unblock any in-flight Read.
SetReadDeadline lets in-flight Reads finish their current chunk cleanly. Close would unblock with an abrupt close error and prevent us from sending a polite final response. The deadline approach is cooperative; close is forced.