Basic Usage
4 minute read
This guide covers the essential operations for working with the config package. Learn how to load configuration files, access values, and handle errors.
Loading Configuration Files
The config package automatically detects file formats based on the file extension. Supported formats include JSON, YAML, and TOML.
Simple File Loading
package main
import (
"context"
"log"
"rivaas.dev/config"
)
func main() {
cfg := config.MustNew(
config.WithFile("config.yaml"),
)
if err := cfg.Load(context.Background()); err != nil {
log.Fatalf("failed to load config: %v", err)
}
}
Multiple File Formats
You can load multiple configuration files of different formats:
cfg := config.MustNew(
config.WithFile("config.yaml"), // YAML format
config.WithFile("config.json"), // JSON format
config.WithFile("config.toml"), // TOML format
)
Environment Variables in Paths
You can use environment variables in file paths. This is useful when different environments use different directories:
// Use ${VAR} or $VAR in paths
cfg := config.MustNew(
config.WithFile("${CONFIG_DIR}/app.yaml"), // Expands to actual directory
config.WithFile("${APP_ENV}/overrides.yaml"), // e.g., "production/overrides.yaml"
)
This works with all path-based options: WithFile, WithFileAs, WithConsul, WithConsulAs, WithFileDumper, and WithFileDumperAs.
Built-in Format Support
The config package includes built-in codecs for common formats:
| Format | Extension | Codec Type |
|---|---|---|
| JSON | .json | codec.TypeJSON |
| YAML | .yaml, .yml | codec.TypeYAML |
| TOML | .toml | codec.TypeTOML |
| Environment Variables | - | codec.TypeEnvVar |
Accessing Configuration Values
Once loaded, access configuration using dot notation and type-safe getters.
Dot Notation
Navigate nested configuration structures using dots:
// Given config: { "database": { "host": "localhost", "port": 5432 } }
host := cfg.String("database.host") // "localhost"
port := cfg.Int("database.port") // 5432
Type-Safe Getters
The config package provides type-safe getters for common data types:
// Basic types
stringVal := cfg.String("key")
intVal := cfg.Int("key")
boolVal := cfg.Bool("key")
floatVal := cfg.Float64("key")
// Time and duration
duration := cfg.Duration("timeout")
timestamp := cfg.Time("created_at")
// Collections
slice := cfg.StringSlice("tags")
mapping := cfg.StringMap("metadata")
Getters with Default Values
Use Or variants to provide fallback values:
host := cfg.StringOr("server.host", "localhost")
port := cfg.IntOr("server.port", 8080)
debug := cfg.BoolOr("debug", false)
timeout := cfg.DurationOr("timeout", 30*time.Second)
Generic Getters for Custom Types
For custom types or explicit error handling, use the generic GetE function:
// With error handling
port, err := config.GetE[int](cfg, "server.port")
if err != nil {
log.Printf("invalid port: %v", err)
port = 8080 // fallback
}
// For custom types
type DatabaseConfig struct {
Host string
Port int
}
dbConfig, err := config.GetE[DatabaseConfig](cfg, "database")
if err != nil {
log.Fatalf("invalid database config: %v", err)
}
Error Handling
The config package provides comprehensive error handling through different getter variants.
Short Form (No Error)
Short methods return zero values for missing keys:
cfg.String("nonexistent") // Returns ""
cfg.Int("nonexistent") // Returns 0
cfg.Bool("nonexistent") // Returns false
cfg.StringSlice("nonexistent") // Returns []string{}
cfg.StringMap("nonexistent") // Returns map[string]any{}
This approach is ideal when you want simple access with sensible defaults.
Default Value Form (Or Methods)
Or methods provide explicit fallback values:
host := cfg.StringOr("host", "localhost") // Returns "localhost" if missing
port := cfg.IntOr("port", 8080) // Returns 8080 if missing
debug := cfg.BoolOr("debug", false) // Returns false if missing
timeout := cfg.DurationOr("timeout", 30*time.Second) // Returns 30s if missing
Error Returning Form (E Methods)
Use GetE for explicit error handling:
port, err := config.GetE[int](cfg, "server.port")
if err != nil {
return fmt.Errorf("invalid port configuration: %w", err)
}
// Errors provide context
// Example: "config error: key 'server.port' not found"
ConfigError Structure
When errors occur during loading, they’re wrapped in ConfigError:
type ConfigError struct {
Source string // Where the error occurred (e.g., "source[0]")
Field string // Specific field with the error
Operation string // Operation being performed (e.g., "load")
Err error // Underlying error
}
Example error handling during load:
if err := cfg.Load(context.Background()); err != nil {
// Error message includes context:
// "config error in source[0] during load: file not found: config.yaml"
log.Fatalf("configuration error: %v", err)
}
Nil-Safe Operations
All getter methods handle nil Config instances gracefully:
var cfg *config.Config // nil
// Short methods return zero values (no panic)
cfg.String("key") // Returns ""
cfg.Int("key") // Returns 0
cfg.Bool("key") // Returns false
// Error methods return errors
port, err := config.GetE[int](cfg, "key")
// err: "config instance is nil"
Complete Example
Putting it all together:
package main
import (
"context"
"log"
"time"
"rivaas.dev/config"
)
func main() {
// Create config with file source
cfg := config.MustNew(
config.WithFile("config.yaml"),
)
// Load configuration
if err := cfg.Load(context.Background()); err != nil {
log.Fatalf("failed to load config: %v", err)
}
// Access values with different approaches
// Simple access (with zero values for missing keys)
host := cfg.String("server.host")
// With defaults
port := cfg.IntOr("server.port", 8080)
debug := cfg.BoolOr("debug", false)
// With error handling
timeout, err := config.GetE[time.Duration](cfg, "server.timeout")
if err != nil {
log.Printf("using default timeout: %v", err)
timeout = 30 * time.Second
}
log.Printf("Server: %s:%d (debug: %v, timeout: %v)",
host, port, debug, timeout)
}
Sample config.yaml:
server:
host: localhost
port: 8080
timeout: 30s
debug: true
Next Steps
- Learn about Environment Variables for flexible configuration
- Explore Struct Binding to map config to Go structs
- See Multiple Sources for merging configurations
For complete API details, see the API Reference.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.