How to Manage Application Lifecycle in Go (Start, Run, Shutdown)

Use context.Context with signal handlers to propagate cancellation signals for graceful Go application shutdowns.

Manage the application lifecycle in Go by using context.Context to propagate cancellation signals from signal handlers to your goroutines. Create a parent context that listens for SIGINT or SIGTERM, pass it to your workers, and call cancel() in the signal handler to trigger a graceful shutdown.

package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	go func() {
		<-signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM).Done()
		log.Println("Shutdown signal received")
		cancel()
	}()

	go worker(ctx)

	<-ctx.Done()
	log.Println("Waiting for workers to finish...")
	time.Sleep(2 * time.Second)
	log.Println("Shutdown complete")
}

func worker(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			log.Println("Worker stopping")
			return
		default:
			log.Println("Working...")
			time.Sleep(1 * time.Second)
		}
	}
}