Documentation Index Fetch the complete documentation index at: https://mintlify.com/raystack/salt/llms.txt
Use this file to discover all available pages before exploring further.
The config package provides a comprehensive configuration management solution that merges settings from multiple sources: configuration files, environment variables, command-line flags, and default values.
Features
Multiple Sources : Merge config from YAML files, environment variables, and CLI flags
Priority Order : Command-line flags → Environment variables → Config file → Defaults
Validation : Built-in struct validation using go-playground/validator
Type Safety : Strongly-typed configuration with struct tags
Dynamic Binding : Automatic flag binding using reflection
App Config Support : Platform-specific configuration file paths
Installation
go get github.com/raystack/salt/config
Quick Start
package main
import (
" log "
" github.com/raystack/salt/config "
" github.com/spf13/pflag "
)
type Config struct {
Server struct {
Port int `mapstructure:"server.port" default:"8080" validate:"required,min=1"`
Host string `mapstructure:"server.host" default:"localhost" validate:"required"`
} `mapstructure:"server"`
LogLevel string `mapstructure:"log.level" default:"info" validate:"oneof=debug info warn error"`
}
func main () {
loader := config . NewLoader (
config . WithFile ( "./config.yaml" ),
config . WithEnvPrefix ( "MYAPP" ),
)
cfg := & Config {}
if err := loader . Load ( cfg ); err != nil {
log . Fatalf ( "Failed to load config: %v " , err )
}
log . Printf ( "Server will run on %s : %d " , cfg . Server . Host , cfg . Server . Port )
}
Core Types
Loader
type Loader struct {
// Internal fields
}
The main configuration loader that manages reading from multiple sources.
Option
type Option func ( c * Loader )
Functional option for configuring the Loader.
Creating a Loader
NewLoader
func NewLoader ( options ... Option ) * Loader
Creates a new configuration loader with the specified options.
Example:
loader := config . NewLoader (
config . WithFile ( "./config.yaml" ),
config . WithEnvPrefix ( "MYAPP" ),
)
Loader Options
WithFile
func WithFile ( configFilePath string ) Option
Specifies the configuration file path.
loader := config . NewLoader (
config . WithFile ( "/etc/myapp/config.yaml" ),
)
WithEnvPrefix
func WithEnvPrefix ( prefix string ) Option
Sets a prefix for environment variables. Dots in config keys are replaced with underscores.
loader := config . NewLoader (
config . WithEnvPrefix ( "MYAPP" ),
)
// Reads MYAPP_SERVER_PORT for server.port
WithFlags
func WithFlags ( flags * pflag . FlagSet ) Option
Binds command-line flags dynamically based on cmdx struct tags.
flags := pflag . NewFlagSet ( "myapp" , pflag . ExitOnError )
flags . Int ( "server.port" , 8080 , "Server port" )
loader := config . NewLoader (
config . WithFlags ( flags ),
)
WithAppConfig
func WithAppConfig ( app string ) Option
Sets up application-specific configuration with platform-aware file paths:
Linux/Mac: ~/.config/raystack/<app>.yml
Windows: %APPDATA%\raystack\<app>.yml
loader := config . NewLoader (
config . WithAppConfig ( "myapp" ),
)
Loader Methods
Load
func ( l * Loader ) Load ( config interface {}) error
Reads configuration from all sources and merges them into the provided struct.
Priority Order:
Command-line flags (highest)
Environment variables
Configuration file
Default values (lowest)
Example:
cfg := & Config {}
if err := loader . Load ( cfg ); err != nil {
log . Fatal ( err )
}
Init
func ( l * Loader ) Init ( config interface {}) error
Initializes a configuration file with default values.
cfg := & Config {}
if err := loader . Init ( cfg ); err != nil {
log . Fatal ( err )
}
Get
func ( l * Loader ) Get ( key string ) interface {}
Retrieves a configuration value by key.
port := loader . Get ( "server.port" )
Set
func ( l * Loader ) Set ( key string , value interface {})
Updates a configuration value in memory (not persisted).
loader . Set ( "server.port" , 9090 )
Save
func ( l * Loader ) Save () error
Writes the current configuration to the configured file.
if err := loader . Save (); err != nil {
log . Fatal ( err )
}
View
func ( l * Loader ) View () ( string , error )
Returns the current configuration as formatted JSON.
jsonConfig , err := loader . View ()
if err != nil {
log . Fatal ( err )
}
fmt . Println ( jsonConfig )
Configure your structs using the following tags:
mapstructure
Maps configuration keys to struct fields.
type Config struct {
Port int `mapstructure:"server.port"`
}
default
Specifies default values.
type Config struct {
Port int `mapstructure:"server.port" default:"8080"`
}
validate
Defines validation rules using go-playground/validator syntax.
type Config struct {
Port int `mapstructure:"server.port" validate:"required,min=1,max=65535"`
Level string `mapstructure:"log.level" validate:"oneof=debug info warn error"`
}
cmdx
Binds command-line flags when using WithFlags option.
type Config struct {
Port int `mapstructure:"server.port" cmdx:"server.port"`
}
Configuration File Example
config.yaml:
server :
port : 8080
host : localhost
timeout : 30s
database :
driver : postgres
url : postgres://localhost:5432/mydb
max_open_conns : 25
log :
level : info
format : json
Environment Variables
With WithEnvPrefix("MYAPP"), you can override configuration:
export MYAPP_SERVER_PORT = 9090
export MYAPP_LOG_LEVEL = debug
Note: Dots in keys are replaced with underscores in environment variables.
Complete Example with Flags
package main
import (
" fmt "
" log "
" os "
" github.com/raystack/salt/config "
" github.com/spf13/pflag "
)
type Config struct {
ServerPort int `mapstructure:"server.port" cmdx:"server.port" default:"8080" validate:"required,min=1"`
LogLevel string `mapstructure:"log.level" cmdx:"log.level" default:"info" validate:"required,oneof=debug info warn error"`
}
func main () {
flags := pflag . NewFlagSet ( "example" , pflag . ExitOnError )
flags . Int ( "server.port" , 8080 , "Server port" )
flags . String ( "log.level" , "info" , "Log level" )
loader := config . NewLoader (
config . WithFile ( "./config.yaml" ),
config . WithEnvPrefix ( "MYAPP" ),
config . WithFlags ( flags ),
)
flags . Parse ( os . Args [ 1 :])
cfg := & Config {}
if err := loader . Load ( cfg ); err != nil {
log . Fatalf ( "Failed to load configuration: %v " , err )
}
fmt . Printf ( "Server Port: %d \n " , cfg . ServerPort )
fmt . Printf ( "Log Level: %s \n " , cfg . LogLevel )
}
Best Practices
Provide Sensible Defaults
Use default tags for non-critical settings: LogLevel string `default:"info"`
Use struct comments to document configuration options: // ServerPort is the HTTP server listening port
ServerPort int `mapstructure:"server.port"`
Error Handling
The Load method returns detailed errors for:
Missing files : Returns warning, falls back to defaults
Invalid struct : Returns error if not a pointer to struct
Validation failures : Returns detailed validation errors
Type mismatches : Returns unmarshal errors
if err := loader . Load ( cfg ); err != nil {
// Check for validation errors
if validationErr , ok := err .( validator . ValidationErrors ); ok {
for _ , e := range validationErr {
fmt . Printf ( "Field %s failed validation: %s \n " , e . Field (), e . Tag ())
}
}
}