package main import ( "context" "fmt" "log/slog" "net/http" "os" "os/signal" "syscall" "time" ) func main() { slog.Info(fmt.Sprintf("starting app on pid=%d\n", os.Getpid())) // create a channel to receive a os.Signal (type) with size of 1 sigs := make(chan os.Signal, 1) // send to channel this signals signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP) // starting the server in a go func srv := startServer() // app will wait here, waiting to receive a channel sig := <-sigs slog.Info(fmt.Sprintf("received signal=%s\n", sig)) // create a context with timeout to wait server shutdown ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() err := srv.Shutdown(ctx) if err != nil { slog.Error(err.Error()) } } func startServer() *http.Server { mux := http.NewServeMux() mux.HandleFunc("/ping", PongHandler) srv := &http.Server{Addr: ":4000", Handler: mux} go func() { err := srv.ListenAndServe() slog.Info(fmt.Sprintf("server returned this error=%s\n", err)) }() return srv } func PongHandler(response http.ResponseWriter, request *http.Request) { // a sleep to given you time to send signal time.Sleep(5 * time.Second) fmt.Fprintln(response, "pong") }