Signals

Handling signals in Go #

A common pattern in Go is to wait for the user (or a scheduler like Kubernetes) to terminate the process. Consider the following use case where we run a HTTP server.

package main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"time"
)

func main() {
	http.HandleFunc("/hello", func(rw http.ResponseWriter, r *http.Request) {
		rw.WriteHeader(http.StatusOK)
	})

	srv := &http.Server{
		Handler: http.DefaultServeMux,
		Addr:    ":8080",
	}

	go func() {
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			fmt.Printf("Failed to serve: %v\n", err)
		}
	}()

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt)
	fmt.Println("Waiting for signal..")
	<-ch
	fmt.Println("Exiting..")

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		fmt.Printf("Failed to shutdown http server: %v\n", err)
	}
}