Skip to content

Instantly share code, notes, and snippets.

@blixt
Last active October 30, 2017 19:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save blixt/6b1efd87c986ee71d548281047f6e4bc to your computer and use it in GitHub Desktop.
Save blixt/6b1efd87c986ee71d548281047f6e4bc to your computer and use it in GitHub Desktop.
Minimal code needed to implement graceful shutdown of HTTP server in Go 1.8 and up.
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World!"))
})
// This server will use http.DefaultServeMux, set Handler here to override.
server := &http.Server{Addr: ":8080"}
// Serve HTTP connections and wait for server to close.
done := make(chan bool, 1)
go func() {
log.Printf("Serving on %s...", server.Addr)
if err := server.ListenAndServe(); err != http.ErrServerClosed {
log.Printf("Failed to serve HTTP: %v", err)
done <- true
}
}()
// Listen for signals to shut down server.
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
<-c
// We received interrupt/terminate signal, don't listen for more.
signal.Stop(c)
log.Printf("Shutting down...")
// Shut down the HTTP server (this won't wait for hijacked connections).
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Printf("Failed to shut down HTTP server gracefully: %v", err)
// Force kill connections instead.
if err := server.Close(); err != nil {
log.Printf("Additionally, received error when closing: %v", err)
}
}
// Tell the main thread that we're done.
done <- true
}()
// Wait for server to stop serving.
<-done
// TODO: Put your other shutdown logic here.
// ...
log.Println("Good bye!")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment