// main is the composition root for the application. // It wires together config, logger, and domain services — nothing more. // Business logic lives in internal/; cmd/ is deliberately thin. package main import ( "fmt" "os" "gitea.djmil.dev/djmil/go-template/internal/config" "gitea.djmil.dev/djmil/go-template/internal/greeter" "gitea.djmil.dev/djmil/go-template/internal/logger" ) func main() { if err := run(); err != nil { fmt.Fprintf(os.Stderr, "fatal: %v\n", err) os.Exit(1) } } func run() error { // ── Config ──────────────────────────────────────────────────────────────── cfgPath := os.Getenv("CONFIG_PATH") if cfgPath == "" { cfgPath = "config/dev.yaml" } cfg, err := config.Load(cfgPath) if err != nil { return fmt.Errorf("loading config: %w", err) } // ── Logger ──────────────────────────────────────────────────────────────── var log *logger.Logger if cfg.App.Env == "dev" { log, err = logger.NewDevelopment() } else { log, err = logger.New(cfg.Logger.Level) } if err != nil { return fmt.Errorf("creating logger: %w", err) } defer log.Sync() log.WithFields(map[string]any{ "app": cfg.App.Name, "env": cfg.App.Env, }).Info("starting up") // ── Services ────────────────────────────────────────────────────────────── greetSvc := greeter.New(log) // ── Example usage ───────────────────────────────────────────────────────── msg, err := greetSvc.Greet("Gopher") if err != nil { return fmt.Errorf("greeter: %w", err) } log.WithField("message", msg).Info("greeting complete") fmt.Printf("%s (listening on :%d)\n", msg, cfg.App.Port) return nil }