Loader API
Complete method reference for the Loader type. Loader is the core type of the env library, providing environment variable loading, storage, and access functionality.
TIP
All methods of Loader are thread-safe and can be called concurrently from multiple goroutines.
Type Definition
type Loader struct {
// Contains private fields
}
// Compile-time interface implementation checks
var _ EnvLoader = (*Loader)(nil)
var _ io.Closer = (*Loader)(nil)Creation
New
func New(cfg ...Config) (*Loader, error)Creates a new loader instance.
Parameters:
cfg- optional configuration options. When not provided or a zero-value Config is passed,DefaultConfig()is automatically used.
Returns:
*Loader- loader instanceerror- configuration validation error
Behavior:
- Validates configuration
- Creates internal components (validator, auditor, expander)
- Automatically loads files if
cfg.Filenamesis non-empty - Automatically applies to system environment if
cfg.AutoApplyis true
// Use default configuration
loader, err := env.New()
// Use custom configuration
cfg := env.DefaultConfig()
cfg.Filenames = []string{".env"}
cfg.AutoApply = true
loader, err := env.New(cfg)
if err != nil {
panic(err)
}
defer loader.Close()File Loading
LoadFiles
func (l *Loader) LoadFiles(filenames ...string) errorLoads one or more configuration files.
Parameters:
filenames- list of file paths; defaults to loading.envwhen empty
Returns:
error- load error
Behavior:
- Loads in order; later files overwrite earlier ones (controlled by
OverwriteExistingconfig) - Auto-detects file format (.env, JSON, YAML)
- Determines behavior for missing files based on
FailOnMissingFileconfig - If
AutoApplyis true, automatically applies after loading
// Load default .env file
err := loader.LoadFiles()
// Load specified files
err := loader.LoadFiles(".env", ".env.local")
// Mixed formats
err := loader.LoadFiles("config.env", "settings.json", "secrets.yaml")Error types:
ErrFileNotFound- file not found (whenFailOnMissingFile=true)ErrFileTooLarge- file exceeds size limitErrClosed- loader has been closed*ParseError- parse error*JSONError- JSON parse error*YAMLError- YAML parse error*SecurityError- file path security check failed (e.g., path traversal attack)
Format detection rules:
| Extension | Format |
|---|---|
.env | FormatEnv |
.json | FormatJSON |
.yaml, .yml | FormatYAML |
| Other | FormatAuto (uses .env parser) |
Getting Values
Key Resolution
All getter methods support smart key resolution:
| Input Key | Resolved Result |
|---|---|
"DATABASE_HOST" | "DATABASE_HOST" (exact match) |
"database.host" | "DATABASE_HOST" (dots to underscores) |
"app.name" | "APP_NAME" (uppercase + underscores) |
"servers.0.host" | "SERVERS_0_HOST" (array index) |
Resolution order:
- Exact match - directly look up the key name
- Uppercase conversion - simple keys try uppercase version
- Path resolution - dot paths are converted to underscore format
- Index fallback - index access falls back to comma-separated values
GetString
func (l *Loader) GetString(key string, defaultValue ...string) stringGets a string value. Supports dot-path resolution.
Parameters:
key- key name (supports exact match, uppercase conversion, dot path)defaultValue- optional default value
Returns:
string- value or default value (returns empty string when not found and no default)
// Basic usage
host := loader.GetString("HOST", "localhost")
// Dot-path access (JSON/YAML nested structures)
dbHost := loader.GetString("database.host", "localhost")
appName := loader.GetString("app.name")
// Returns empty string when no default
value := loader.GetString("NON_EXISTENT") // ""GetInt
func (l *Loader) GetInt(key string, defaultValue ...int64) int64Gets an integer value. Supports dot-path resolution.
Parameters:
key- key name (supports dot path)defaultValue- optional default value, typeint64
Returns:
int64- value or default value (returns 0 when not found and no default)
port := loader.GetInt("PORT", 8080)
maxConn := loader.GetInt("database.max_connections", 10)
// Returns 0 when no default
value := loader.GetInt("NON_EXISTENT") // 0GetBool
func (l *Loader) GetBool(key string, defaultValue ...bool) boolGets a boolean value. Supports dot-path resolution.
Parameters:
key- key name (supports dot path)defaultValue- optional default value
Returns:
bool- value or default value (returns false when not found and no default)
Supported values:
- Truthy:
true,1,yes,on,enabled - Falsy:
false,0,no,off,disabled
debug := loader.GetBool("DEBUG", false)
cacheEnabled := loader.GetBool("cache.enabled", true)
// Returns false when no default
value := loader.GetBool("NON_EXISTENT") // falseGetUint64
func (l *Loader) GetUint64(key string, defaultValue ...uint64) uint64Gets an unsigned integer value. Supports dot-path resolution.
Parameters:
key- key name (supports dot path)defaultValue- optional default value, typeuint64
Returns:
uint64- value or default value (returns 0 when not found and no default)
port := loader.GetUint64("PORT", 8080)
maxSize := loader.GetUint64("MAX_SIZE", 1024)
// Returns 0 when no default
value := loader.GetUint64("NON_EXISTENT") // 0GetFloat64
func (l *Loader) GetFloat64(key string, defaultValue ...float64) float64Gets a floating-point value. Supports dot-path resolution.
Parameters:
key- key name (supports dot path)defaultValue- optional default value, typefloat64
Returns:
float64- value or default value (returns 0 when not found and no default)
rate := loader.GetFloat64("RATE", 0.5)
threshold := loader.GetFloat64("THRESHOLD")
// Returns 0 when no default
value := loader.GetFloat64("NON_EXISTENT") // 0GetDuration
func (l *Loader) GetDuration(key string, defaultValue ...time.Duration) time.DurationGets a duration value. Supports dot-path resolution.
Parameters:
key- key name (supports dot path)defaultValue- optional default value
Returns:
time.Duration- value or default value (returns 0 when not found and no default)
Supported formats: ns, us, ms, s, m, h (e.g., 30s, 5m, 1h30m)
timeout := loader.GetDuration("TIMEOUT", 30*time.Second)
ttl := loader.GetDuration("cache.ttl", 5*time.Minute)
// Returns 0 when no default
value := loader.GetDuration("NON_EXISTENT") // 0GetSecure
func (l *Loader) GetSecure(key string) *SecureValueGets a secure value (sensitive data protection).
Parameters:
key- key name
Returns:
*SecureValue- defensive copy of the secure value; caller is responsible for releasing; returns nil if the key doesn't exist or loader is closed
secret := loader.GetSecure("API_SECRET")
if secret != nil {
defer secret.Release()
value := secret.Reveal() // plaintext value
masked := secret.Masked() // [SECURE:32 bytes]
}WARNING
You must call Release() or Close() after use to release resources.
TIP
GetSecure returns a copy of the original value, independent from the parent Loader. The caller is responsible for calling Release() or Close().
TIP
See SecureValue API for complete documentation.
Getting Slice Values
Loader does not provide a slice getter method (Go does not support generic methods). Use the standalone generic function GetSliceFrom[T] to get slices from a Loader instance:
// Use standalone generic function
hosts := env.GetSliceFrom[string](loader, "HOSTS")
ports := env.GetSliceFrom[int64](loader, "PORTS", []int64{80})
portsInt := env.GetSliceFrom[int](loader, "PORTS") // also supports intSupported types: string, int, int64, uint, uint64, bool, float64, time.Duration
TIP
See Package Functions - GetSliceFrom for complete documentation.
Lookup
func (l *Loader) Lookup(key string) (string, bool)Checks whether a key exists and gets its value. Supports dot-path resolution.
Parameters:
key- key name (supports dot path)
Returns:
string- value (leading/trailing whitespace removed)bool- whether it exists
value, exists := loader.Lookup("API_KEY")
if !exists {
// key does not exist
}
// Dot path
if value, exists := loader.Lookup("database.host"); exists {
fmt.Println(value)
}
// Index access (falls back to comma-separated value)
// HOSTS=localhost,example.com
if value, exists := loader.Lookup("hosts.0"); exists {
fmt.Println(value) // "localhost"
}Set and Delete
Set
func (l *Loader) Set(key, value string) errorSets an environment variable.
Parameters:
key- key namevalue- value
Returns:
error- set error
Behavior:
- Validates key name validity
- If
ValidateValuesis true, validates value safety - If
OverwriteExistingis false and key already exists, skips (returns nil) - If
AutoApplyis true, also sets in the system environment
err := loader.Set("CUSTOM_KEY", "value")
if err != nil {
// Handle error
}Error types:
*ValidationError- invalid key name format (Field="key")*SecurityError- key is forbidden (matchable witherrors.Is(err, env.ErrSecurityViolation))ErrInvalidValue- invalid value (whenValidateValuesis true, value contains null bytes, control characters, or other unsafe content)ErrClosed- loader has been closed
Delete
func (l *Loader) Delete(key string) errorDeletes an environment variable.
Parameters:
key- key name
Returns:
error- delete error
Behavior:
- If the variable has been applied to the system environment, also removes it from the system environment
err := loader.Delete("TEMP_KEY")
if err != nil {
panic(err)
}Collection Operations
Keys
func (l *Loader) Keys() []stringGets all key names.
Returns:
[]string- key name list; returns nil if loader is closed
keys := loader.Keys()
for _, key := range keys {
fmt.Println(key)
}All
func (l *Loader) All() map[string]stringGets all key-value pairs.
Returns:
map[string]string- key-value mapping; returns nil if loader is closed
all := loader.All()
for key, value := range all {
fmt.Printf("%s=%s\n", key, value)
}Len
func (l *Loader) Len() intGets the variable count.
Returns:
int- variable count; returns 0 if loader is closed
count := loader.Len()
fmt.Printf("Loaded %d variables\n", count)Apply to System
Apply
func (l *Loader) Apply() errorApplies variables to the system environment (os.Environ).
Returns:
error- apply error
Behavior:
- Iterates over all loaded variables
- Determines whether to overwrite existing system environment variables based on
OverwriteExistingconfig - After applying, accessible via
os.Getenv()
Error types:
ErrClosed- loader has been closed- Wrapped
oserror - failed to set environment variable (key name masked, sensitive key names not exposed in error message)
err := loader.Apply()
if err != nil {
panic(err)
}
// After that, os.Getenv() can access it too
host := os.Getenv("HOST")IsApplied
func (l *Loader) IsApplied() boolChecks whether variables have been applied to the system environment.
Returns:
bool- whether applied
if loader.IsApplied() {
// Variables have been applied to os.Environ
}Status Queries
LoadTime
func (l *Loader) LoadTime() time.TimeReturns the time of the last file load.
Returns:
time.Time- load time; returns zero value if never loaded
loadTime := loader.LoadTime()
if !loadTime.IsZero() {
fmt.Printf("Last load time: %v\n", loadTime)
}Config
func (l *Loader) Config() ConfigReturns the loader's configuration.
Returns:
Config- configuration (should be treated as read-only)
WARNING
The returned Config should be treated as read-only. Modifying fields like KeyPattern, AllowedKeys, ForbiddenKeys, RequiredKeys may affect loader behavior. For a safe mutable copy, manually copy the required fields.
cfg := loader.Config()
fmt.Printf("Max file size: %d\n", cfg.MaxFileSize)Validation and Mapping
Validate
func (l *Loader) Validate() errorValidates that required keys exist.
Returns:
error- validation error
Behavior:
- Checks that all keys specified in
ValidationConfig.RequiredKeysexist
cfg := env.DefaultConfig()
cfg.RequiredKeys = []string{"DB_HOST", "API_KEY"}
loader, _ := env.New(cfg)
loader.LoadFiles(".env")
if err := loader.Validate(); err != nil {
// Missing required keys
var missingErr *env.ValidationError
if errors.As(err, &missingErr) {
fmt.Printf("Missing: %s\n", missingErr.Field)
}
}ParseInto
func (l *Loader) ParseInto(v any) errorMaps environment variables to a struct.
Parameters:
v- struct pointer
Returns:
error- mapping error
Supported tags:
env:"KEY"- specifies the environment variable nameenv:"-"- ignore this fieldenvDefault:"value"- specifies a default value
Slice fields are separated by comma , by default (spaces around the separator are automatically removed); there is no custom separator tag.
type Config struct {
Host string `env:"HOST" envDefault:"localhost"`
Port int64 `env:"PORT" envDefault:"8080"`
Debug bool `env:"DEBUG" envDefault:"false"`
Hosts []string `env:"HOSTS"`
Ignored string `env:"-"`
}
var cfg Config
err := loader.ParseInto(&cfg)
if err != nil {
panic(err)
}Resource Release
Close
func (l *Loader) Close() errorReleases resources and clears storage.
Returns:
error- close error
Behavior:
- Securely zeros all stored sensitive data
- If the loader owns a ComponentFactory, also closes the factory
- Safe to close; multiple calls return nil
loader, _ := env.New(cfg)
defer loader.Close()
// Use loader...WARNING
After closing, all operations return errors or zero values:
LoadFiles→ErrClosedGetString→ returns empty valueSet→ErrClosedKeys→ returns nilLen→ returns 0
IsClosed
func (l *Loader) IsClosed() boolChecks whether the loader has been closed.
Returns:
bool- whether closed
if loader.IsClosed() {
// loader has been closed
}Complete Example
package main
import (
"errors"
"fmt"
"log"
"os"
"time"
"github.com/cybergodev/env"
)
func main() {
// Create production configuration
cfg := env.ProductionConfig()
cfg.RequiredKeys = []string{"DB_HOST", "API_KEY"}
cfg.AuditHandler = env.NewJSONAuditHandler(os.Stdout)
// Create loader
loader, err := env.New(cfg)
if err != nil {
log.Fatal(err)
}
defer loader.Close()
// Load files
if err := loader.LoadFiles(".env", ".env.production"); err != nil {
if errors.Is(err, env.ErrFileNotFound) {
log.Fatal("Configuration file not found")
}
log.Fatal(err)
}
// Validate required keys
if err := loader.Validate(); err != nil {
log.Fatal("Missing required configuration:", err)
}
// Read configuration
host := loader.GetString("DB_HOST")
port := loader.GetInt("DB_PORT", 5432)
debug := loader.GetBool("DEBUG", false)
timeout := loader.GetDuration("TIMEOUT", 30*time.Second)
fmt.Printf("Server: %s:%d\n", host, port)
fmt.Printf("Debug: %v, Timeout: %v\n", debug, timeout)
// Sensitive data
secret := loader.GetSecure("API_KEY")
if secret != nil {
defer secret.Release()
fmt.Printf("API Key length: %d\n", secret.Length())
}
// Apply to system environment
if err := loader.Apply(); err != nil {
log.Fatal(err)
}
// All variables
fmt.Printf("Loaded %d variables\n", loader.Len())
fmt.Printf("Load time: %v\n", loader.LoadTime())
}Related Documentation
- Package Functions - Package-level convenience functions
- Config API - Configuration options
- SecureValue API - Secure value handling
- Interfaces - All interface definitions