Documentation
¶
Overview ¶
Package gokart provides thin wrappers around best-in-class Go packages with sensible defaults.
GoKart is an opinionated service toolkit. Every component must justify its existence - we wrap battle-tested packages, not reinvent them.
Components ¶
Root module (github.com/dotcommander/gokart):
- Config: viper wrapper for config files + env vars
- State: JSON state persistence for CLI tools
- Server: HTTP server with graceful shutdown
Submodules:
- gokart/logger: slog wrapper with JSON/text formatting
- gokart/cli: CLI framework wrapping cobra + lipgloss
- gokart/web: HTTP router, client, templ helpers, validator
- gokart/postgres: pgx/v5 connection pool
- gokart/sqlite: modernc.org/sqlite (zero CGO) with WAL mode
- gokart/cache: go-redis/v9 with convenience methods
- gokart/migrate: goose/v3 schema migrations
- gokart/ai: OpenAI client factory functions
Design Principles ¶
- Thin wrappers: No business logic, just factory functions
- Sensible defaults: Zero-config works for development and production
- Best-in-class: Wrap proven packages, don't reinvent
- Fight for inclusion: stdlib-sufficient things stay in stdlib
Quick Start ¶
// Logger
log := logger.New(logger.Config{Level: "info", Format: "json"})
// Config
cfg, err := gokart.LoadConfig[AppConfig]("config.yaml")
// Router (gokart/web)
router := web.NewRouter(web.RouterConfig{Middleware: web.StandardMiddleware})
// PostgreSQL (gokart/postgres)
pool, err := postgres.Open(ctx, "postgres://localhost/mydb")
// Cache (gokart/cache)
c, err := cache.Open(ctx, "localhost:6379")
// Migrations (gokart/migrate)
migrate.Postgres(ctx, db, "migrations")
CLI Subpackage ¶
For CLI applications, use the gokart/cli subpackage which wraps cobra and lipgloss:
import "github.com/dotcommander/gokart/cli"
app := cli.NewApp("myapp", "1.0.0").
WithDescription("My application").
WithStandardFlags()
app.Run()
Not Included ¶
GoKart intentionally excludes things where stdlib is sufficient:
- Error handling: use errors.Is/As and fmt.Errorf("%w", err)
- File operations: use os, io, filepath
- String manipulation: use strings
- Environment variables: viper.AutomaticEnv() handles this
Domain-specific packages (AI/ML, document processing) belong in separate modules.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func LoadConfig ¶
LoadConfig loads configuration from the first available file path into type T.
Features:
- Supports multiple config paths (first found wins)
- Automatic environment variable binding
- DOT to UNDERSCORE env key mapping (e.g., db.host → DB_HOST)
Supported formats: JSON, YAML, TOML, HCL, envfile, Java properties
Example:
type Config struct {
DB struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
} `mapstructure:"db"`
}
cfg, err := gokart.LoadConfig[Config]("config.yaml", "config.json")
func LoadConfigWithDefaults ¶
LoadConfigWithDefaults loads configuration with default values pre-populated.
The defaults parameter provides fallback values that will be overridden by values from config files or environment variables.
Example:
defaults := Config{
DB: struct{Host string; Port int}{
Host: "localhost",
Port: 5432,
},
}
cfg, err := gokart.LoadConfigWithDefaults(defaults, "config.yaml")
func LoadState ¶
LoadState loads typed state from ~/.config/{appName}/{filename}.
Returns zero value and os.ErrNotExist if the file doesn't exist. This allows callers to distinguish between missing file and parse errors.
Example:
state, err := gokart.LoadState[AppState]("myapp", "state.json")
if errors.Is(err, os.ErrNotExist) {
// First run, use defaults
state = AppState{WindowSize: 800}
} else if err != nil {
return err
}
func SaveState ¶
SaveState saves typed state to ~/.config/{appName}/{filename}.
The file is written as indented JSON for human readability. Directory is created with 0755, files with 0644 permissions.
Example:
type AppState struct {
LastOpened string `json:"last_opened"`
WindowSize int `json:"window_size"`
}
err := gokart.SaveState("myapp", "state.json", AppState{
LastOpened: "/path/to/file",
WindowSize: 1024,
})
Types ¶
This section is empty.