This repository is to demo how to implement graceful shutdown with golang
Why Graceful shutdwon ?
- Release Resource Properly
- Prevent Memory Leak for unexpected interrupt
- Build
type Server struct {
server *http.Server
}
func NewServer() *Server {
mux := http.NewServeMux()
mux.HandleFunc("/slow", func(w http.ResponseWriter, r *http.Request) {
log.Println("Slow request started...")
time.Sleep(8 * time.Second)
fmt.Fprintf(w, "Slow request completed at %v\n", time.Now())
})
return &Server{
server: &http.Server{
Addr: ":8080",
Handler: mux,
},
}
}- Run
func (s *Server) Run(ctx context.Context,
shutdownTimeout time.Duration,
) error {
// Run logic
}- Setup channel for signal system interupt and SIGTERM
// just catch any signal below
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
select {
case err := <-serverErr:
return err
case <-stop:
log.Println("Shutdown signal received")
case <-ctx.Done():
log.Println("Context cancelled")
}- Shutdown with timeout
shutdownCtx, cancel := context.WithTimeout(
context.Background(), // prevent inheriant cancellation
shutdownTimeout,
)
defer cancel() // clear up resource
if err := s.server.Shutdown(shutdownCtx); err != nil {
if closeErr := s.server.Close(); closeErr != nil {
return errors.Join(err, closeErr)
}
return err
}