Go to file

Config

A simple, thread-safe configuration management package for Go applications that supports TOML files, command-line argument overrides, and registered default values.

Features

  • Thread-Safe Operations: Uses sync.RWMutex to protect concurrent access during all configuration operations.
  • TOML Configuration: Uses BurntSushi/toml for loading and saving configuration files.
  • Command-Line Overrides: Allows overriding configuration values using dot notation in CLI arguments (e.g., --server.port 9090).
  • Path-Based Access: Register configuration paths with default values for direct, consistent access with clear error messages.
  • Struct Registration: Register an entire struct as configuration defaults, using struct tags to determine paths.
  • Atomic File Operations: Ensures configuration files are written atomically to prevent corruption.
  • Path Validation: Validates configuration path segments against TOML key requirements.
  • Type Conversions: Helper methods for converting configuration values to common Go types with detailed error messages.
  • Hierarchical Data Management: Automatically handles nested structures through dot notation.

Installation

go get github.com/LixenWraith/config

Dependencies will be automatically fetched:

github.com/BurntSushi/toml
github.com/mitchellh/mapstructure

Usage

Basic Usage Pattern

// 1. Initialize a new Config instance
cfg := config.New()

// 2. Register configuration paths with default values
cfg.Register("server.host", "127.0.0.1")
cfg.Register("server.port", 8080)

// 3. Load configuration from file with CLI argument overrides
err := cfg.Load("app_config.toml", os.Args[1:])
if err != nil {
    if errors.Is(err, config.ErrConfigNotFound) {
        log.Println("Config file not found, using defaults")
    } else {
        log.Fatal(err)
    }
}

// 4. Access configuration values using the registered paths
serverHost, err := cfg.String("server.host")
if err != nil {
    log.Fatal(err)
}

serverPort, err := cfg.Int64("server.port")
if err != nil {
    log.Fatal(err)
}

// 5. Save configuration (creates the file if it doesn't exist)
err = cfg.Save("app_config.toml")

Struct-Based Registration

// Define a configuration struct with TOML tags
type ServerConfig struct {
    Host    string `toml:"host"`
    Port    int64  `toml:"port"`
    Timeout int64  `toml:"timeout"`
    Debug   bool   `toml:"debug"`
}

// Create default configuration
defaults := ServerConfig{
    Host:    "localhost",
    Port:    8080,
    Timeout: 30,
    Debug:   false,
}

// Register the entire struct at once
err := cfg.RegisterStruct("server.", defaults)

Accessing Typed Values

// Use type-specific accessor methods
port, err := cfg.Int64("server.port")
debug, err := cfg.Bool("debug")
rate, err := cfg.Float64("rate.limit")
name, err := cfg.String("server.name")

Using Scan to Populate Structs

// Define a struct matching your configuration
type AppConfig struct {
    ServerName string `toml:"name"`
    ServerPort int64  `toml:"port"`
    Debug      bool   `toml:"debug"`
}

// Create an instance to receive the configuration
var appConfig AppConfig

// Scan the configuration into the struct
err := cfg.Scan("server", &appConfig)
if err != nil {
    log.Fatal(err)
}

API

New() *Config

Creates and returns a new, initialized *Config instance ready for use.

(*Config) Register(path string, defaultValue any) error

Registers a configuration path with a default value.

  • path: Dot-separated path corresponding to the TOML structure. Each segment must be a valid TOML key.
  • defaultValue: The value returned if no other value has been set through Load or Set.
  • Returns: Error (nil on success)

(*Config) RegisterStruct(prefix string, structWithDefaults interface{}) error

Registers all fields of a struct as configuration paths, using struct tags to determine the paths.

  • prefix: Prefix to prepend to all generated paths (e.g., "server.").
  • structWithDefaults: Struct containing default values. Fields must have toml tags.
  • Returns: Error if registration fails for any field.

(*Config) GetRegisteredPaths(prefix string) map[string]bool

Returns all registered configuration paths that start with the given prefix.

  • prefix: Path prefix to filter by (e.g., "server.").
  • Returns: Map where keys are the registered paths that match the prefix.

(*Config) Get(path string) (any, bool)

Retrieves a configuration value using the registered path.

  • path: The dot-separated path string used during registration.
  • Returns: The configuration value and a boolean indicating if the path was registered.
  • Value precedence: CLI Argument > Config File Value > Registered Default Value

(*Config) String(path string) (string, error)

(*Config) Int64(path string) (int64, error)

(*Config) Bool(path string) (bool, error)

(*Config) Float64(path string) (float64, error)

Type-specific accessor methods that retrieve and attempt to convert configuration values to the desired type.

  • path: The dot-separated path string used during registration.
  • Returns: The typed value and an error (nil on success).
  • Errors: Detailed error messages when:
    • The path is not registered
    • The value cannot be converted to the requested type
    • Type conversion fails (with the specific reason)

(*Config) Set(path string, value any) error

Updates a configuration value using the registered path.

  • path: The dot-separated path string used during registration.
  • value: The new value to set.
  • Returns: Error if the path wasn't registered or if setting the value fails.

(*Config) Unregister(path string) error

Removes a configuration path and all its children from the configuration.

  • path: The dot-separated path string used during registration.
  • Effects:
    • Removes the specified path
    • Recursively removes all child paths (e.g., unregistering "server" also removes "server.host", "server.port", etc.)
    • Completely removes both registration and data
  • Returns: Error if the path wasn't registered.

(*Config) Scan(basePath string, target any) error

Decodes a section of the configuration into a struct or map.

  • basePath: Dot-separated path to the configuration subtree.
  • target: Pointer to a struct or map where the configuration should be unmarshaled.
  • Returns: Error if unmarshaling fails.

(*Config) Load(filePath string, args []string) error

Loads configuration from a TOML file and merges overrides from command-line arguments.

  • filePath: Path to the TOML configuration file.
  • args: Command-line arguments (e.g., os.Args[1:]).
  • Returns: Error on failure, which can be checked with:
    • errors.Is(err, config.ErrConfigNotFound) to detect missing file
    • errors.Is(err, config.ErrCLIParse) to detect CLI parsing errors

(*Config) Save(filePath string) error

Saves the current configuration to the specified TOML file path, performing an atomic write.

  • filePath: Path where the TOML configuration file will be written.
  • Returns: Error if marshaling or file operations fail, nil on success.

License

BSD-3-Clause

Description
No description provided
Readme BSD-3-Clause 503 KiB
Languages
Go 100%