8.1 KiB
lixenwraith/config Quick Reference Guide
This guide details the lixenwraith/config package for thread-safe Go configuration.
It supports multiple sources (files, environment, CLI), type-safe struct population, and live reconfiguration.
Quick Start: Recommended Usage
The recommended pattern uses the Builder with a target struct providing compile-time type safety and eliminating the need for runtime type assertions
package main
import (
"fmt"
"log"
"os"
"github.com/lixenwraith/config"
)
// 1. Define your application's configuration struct
type AppConfig struct {
Server struct {
Host string `toml:"host"`
Port int `toml:"port"`
} `toml:"server"`
Debug bool `toml:"debug"`
}
func main() {
// 2. Create a target instance with defaults
// Method A: Direct initialization (cleaner for simple defaults)
target := &AppConfig{}
target.Server.Host = "localhost"
target.Server.Port = 8080
// Method B: Use WithDefaults() for explicit separation (shown below)
// 3. Use the builder to configure and load all sources
cfg, err := config.NewBuilder().
WithTarget(target). // Enable type-safe mode and register struct fields
// WithDefaults(&AppConfig{...}), // Optional: Override defaults from WithTarget
WithFile("config.toml"). // Load from file (supports .toml, .json, .yaml)
WithEnvPrefix("APP_"). // Load from environment (e.g., APP_SERVER_PORT)
WithArgs(os.Args[1:]). // Load from command-line flags (e.g., --server.port=9090)
Build() // Build the final config object
if err != nil {
log.Fatalf("Config build failed: %v", err)
}
// 4. Access the fully populated, type-safe struct
// The `target` variable is now populated with the final merged values
fmt.Printf("Running on %s:%d\n", target.Server.Host, target.Server.Port)
// Or, retrieve the updated struct at any time (e.g., after a live reload)
latest, _ := cfg.AsStruct()
latestConfig := latest.(*AppConfig)
fmt.Printf("Debug mode: %v\n", latestConfig.Debug)
}
Supported Formats: TOML, JSON, YAML
The package supports multiple file formats. The format is auto-detected from the file extension (.toml, .json, .yaml, .yml) or file content
- To specify a format explicitly, use
Builder.WithFileFormat("json") - The default struct tag for field mapping is
toml, but can be changed withBuilder.WithTagName("json")
Builder Pattern
The Builder is the primary way to construct a Config instance
// NewBuilder creates a new configuration builder
func NewBuilder() *Builder
// Build finalizes configuration; returns the first of any accumulated errors
func (b *Builder) Build() (*Config, error)
// MustBuild is like Build but panics on fatal errors
func (b *Builder) MustBuild() *Config
Builder Methods
WithTarget(target any): (Recommended) Registers fields from the target struct and allows access viaAsStruct()WithDefaults(defaults any): Explicitly sets a struct containing default values, overriding any default values already in struct fromWithTargetWithFile(path string): Sets the configuration file pathWithFileDiscovery(opts FileDiscoveryOptions): Enables automatic config file discovery (searches CLI flags, env vars, XDG paths, and current directory)WithArgs(args []string): Sets the command-line arguments to parse (e.g.,--server.port=9090)WithEnvPrefix(prefix string): Sets the global environment variable prefix (e.g.,MYAPP_)WithSources(sources ...Source): Overrides the default source precedence orderWithTypedValidator(fn any): (Recommended for validation) Adds a type-safe validation function with signaturefunc(c *YourConfigType) errorthat runs after the target struct is populatedWithValidator(fn ValidatorFunc): Adds a validation function that runs before type-safe population, operating on the raw*ConfigobjectWithTagName(tagName string): Sets the primary struct tag for field mapping ("toml","json","yaml")WithPrefix(prefix string): Adds a prefix to all registered paths from a structWithFileFormat(format string): Explicitly sets the file format ("toml","json","yaml","auto")WithSecurityOptions(opts SecurityOptions): Sets security options for file loading (path traversal, file size limits)WithEnvTransform(fn EnvTransformFunc): Sets a custom environment variable mapping functionWithEnvWhitelist(paths ...string): Limits environment variable loading to a specific set of paths
Type-Safe Access & Population
These are the preferred methods for accessing configuration data
AsStruct() (any, error): After usingBuilder.WithTarget(), this method returns the populated, type-safe target struct - This is the primary way to access config after initialization or live reloadScan(basePath string, target any): Populates a struct with values from a specific config path (e.g.,cfg.Scan("server", &serverConf))ScanMap(configMap map[string]any, target any, tagName ...string): Decodes a map[string]any directly into a target struct, useful for plugins or custom config sourcesGetTyped[T](c *Config, path string) (T, error): Retrieves a single value and decodes it to typeT, handling type conversion automaticallyScanTyped[T](c *Config, basePath ...string) (*T, error): A generic wrapper aroundScanthat allocates, populates, and returns a pointer to a struct of typeT
Live Reconfiguration
Enable automatic reloading of configuration when the source file changes
AutoUpdate(): Enables file watching and automatic reloading with default optionsAutoUpdateWithOptions(opts WatchOptions): Enables reloading with custom options (e.g., poll interval, debounce)StopAutoUpdate(): Stops the file watcherWatch() <-chan string: Returns a channel that receives the paths of changed valuesWatchFile(filePath string, formatHint ...string): Switches the watcher to a new file at runtimeIsWatching() bool: Returnstrueif the file watcher is active
The watch channel also receives special notifications: "file_deleted", "permissions_changed", "reload_error:..."
Source Precedence
The default order of precedence (highest to lowest) is:
- CLI: Command-line arguments (
--server.port=9090) - Env: Environment variables (
MYAPP_SERVER_PORT=8888) - File: Configuration file (
config.toml) - Default: Values registered from a struct
This order can be changed via Builder.WithSources() or Config.SetPrecedence()
Dynamic / Legacy Value Access
These methods are for dynamic key-value access that require type assertion and should be avoided when a type-safe struct can be used
Get(path string) (any, bool): Retrieves the final merged value. Theboolindicates if the path was registered. Requires a type assertion, e.g.,port := val.(int64)Set(path string, value any): Updates a value in the highest priority source. The path must be registered firstGetSource(path string, source Source) (any, bool): Retrieves a value from a specific source layerSetSource(path string, source Source, value any): Sets a value for a specific source layer
API Reference Summary
Core Types
Config: The primary thread-safe configuration managerSource: A configuration source (SourceCLI,SourceEnv,SourceFile,SourceDefault)LoadOptions: Options for loading configuration from multiple sourcesBuilder: Fluent API for constructing aConfiginstance
Core Methods
New() *Config: Creates a newConfiginstance.Register(path string, defaultValue any): Registers a path with a default valueRegisterStruct(prefix string, structWithDefaults any): Recursively registers fields from a struct usingtomltagsValidate(required ...string): Checks that all specified required paths have been set from a non-default sourceSave(path string): Atomically saves the current merged configuration state to a fileClone() *Config: Creates a deep copy of the configuration stateDebug() string: Returns a formatted string of all values for debugging