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)
}
}
}