package main import ( "context" "flag" "fmt" "log/slog" "os" "os/signal" "syscall" "time" "github.com/placeholder/golang-template/internal/config" "github.com/placeholder/golang-template/internal/logging" ) func main() { // Parse CLI flags var configPath string flag.StringVar(&configPath, "config", "config/config.yaml", "path to config file") flag.Parse() // Load Configuration cfg, err := config.Load(configPath, "APP") if err != nil { fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err) os.Exit(1) } // Setup Logger logging.Configure(logging.Config{ Level: cfg.Logging.Level, }) ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Handle OS signals go func() { sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) <-sigChan slog.Info("Received shutdown signal") cancel() }() if err := run(ctx); err != nil { slog.Error("Application error", "error", err) os.Exit(1) } } func run(ctx context.Context) error { slog.Info("Starting application...") // Simulate long running process or server start // e.g. server.ListenAndServe() <-ctx.Done() slog.Info("Shutting down application...") // Cleanup with timeout _, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second) defer shutdownCancel() // Pretend to cleanup time.Sleep(100 * time.Millisecond) return nil }