template/cmd/app/main.go
2026-04-07 20:32:27 +00:00

58 lines
2.0 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"
"path/filepath"
"gitea.djmil.dev/go/template/internal/config"
"gitea.djmil.dev/go/template/internal/greeter"
"gitea.djmil.dev/go/template/internal/logger"
"gitea.djmil.dev/go/template/pkg/result"
)
func main() {
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "fatal: %v\n", err)
if stack := result.StackTrace(err); stack != "" {
fmt.Fprintf(os.Stderr, "%s\n", stack)
}
os.Exit(1)
}
}
func run() (err error) {
defer result.Catch(&err)
// ── Config ────────────────────────────────────────────────────────────────
cfg := config.Load()
// ── Logger ────────────────────────────────────────────────────────────────
var log *logger.Logger
if cfg.App.Env == "dev" {
log = logger.NewDevelopment()
} else {
log = result.Of(logger.New(cfg.Logger.Level)).Expect("create logger")
}
log.WithFields(map[string]any{
"app": filepath.Base(os.Args[0]),
"env": cfg.App.Env,
}).Info("starting up")
// ── Services ──────────────────────────────────────────────────────────────
var greetSvc greeter.Greeter = greeter.New(log)
// ── Example usage ─────────────────────────────────────────────────────────
msg := greetSvc.Greet(cfg.Greeter.Name).Expect("greeting")
log.WithField("message", msg).Info("greeting complete")
fmt.Printf("%s (listening on :%d)\n", msg, cfg.App.Port)
return nil
}