go-template/cmd/app/main.go

66 lines
2.1 KiB
Go

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