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.
Thread Safety
All Loader methods 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 used automatically
Returns:
*Loader- Loader instanceerror- Configuration validation error
Behavior:
- Validates configuration validity
- Creates internal components (validator, auditor, expander)
- If
cfg.Filenamesis non-empty, automatically loads files - If
cfg.AutoApplyis true, automatically applies to system environment
// Using default configuration
loader, err := env.New()
// Using 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.envwhen empty
Returns:
error- Loading error
Behavior:
- Loads in order; files loaded later override earlier ones (controlled by
OverwriteExistingconfiguration) - Auto-detects file format (.env, JSON, YAML)
- Behavior when file not found is determined by
FailOnMissingFileconfiguration - 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 is closed*ParseError- Parse error*JSONError- JSON parse error*YAMLError- YAML parse error*SecurityError- File path security validation 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 name resolution:
| Input Key | Resolved |
|---|---|
"DATABASE_HOST" | "DATABASE_HOST" (exact match) |
"database.host" | "DATABASE_HOST" (dot to underscore) |
"app.name" | "APP_NAME" (uppercase + underscore) |
"servers.0.host" | "SERVERS_0_HOST" (array index) |
Resolution Order:
- Exact match - Direct key name lookup
- Uppercase conversion - Simple keys try the uppercase version
- Path resolution - Dot paths converted to underscore format
- Index fallback - Falls back to comma-separated values for index access
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 if 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
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 if not found and no default)
port := loader.GetInt("PORT", 8080)
maxConn := loader.GetInt("database.max_connections", 10)
// Returns 0 when no default value
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 if 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
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 if not found and no default)
port := loader.GetUint64("PORT", 8080)
maxSize := loader.GetUint64("MAX_SIZE", 1024)
// Returns 0 when no default value
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 if not found and no default)
rate := loader.GetFloat64("RATE", 0.5)
threshold := loader.GetFloat64("THRESHOLD")
// Returns 0 when no default value
value := loader.GetFloat64("NON_EXISTENT") // 0GetDuration
func (l *Loader) GetDuration(key string, defaultValue ...time.Duration) time.DurationGets a time 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 if 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
value := loader.GetDuration("NON_EXISTENT") // 0GetSecure
func (l *Loader) GetSecure(key string) *SecureValueGets a secure value (for sensitive data protection).
Parameters:
key- Key name
Returns:
*SecureValue- A defensive copy of the secure value; the caller is responsible for releasing it; returns nil if the key doesn't exist or the loader is closed
secret := loader.GetSecure("API_SECRET")
if secret != nil {
defer secret.Release()
value := secret.Reveal() // plaintext
masked := secret.Masked() // [SECURE:32 bytes]
}Important
You must call Release() or Close() to release resources after use.
Defensive Copy
GetSecure returns a copy of the original value, independent of the parent Loader. The caller is responsible for calling Release() or Close() to release it.
See Also
SecureValue API for complete documentation.
Getting Slice Values
Loader does not provide slice getter methods (Go does not support generic methods). Use the standalone generic function GetSliceFrom[T] to get slices from a Loader instance:
// Using 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
See Also
Package Functions - GetSliceFrom for complete documentation.
Lookup
func (l *Loader) Lookup(key string) (string, bool)Checks if a key exists and gets its value. Supports dot path resolution.
Parameters:
key- Key name (supports dot path)
Returns:
string- Value (leading and trailing whitespace removed)bool- Whether the key 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 values)
// 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- Setting error
Behavior:
- Validates key name validity
- If
ValidateValuesis true, validates value safety - If
OverwriteExistingis false and the key already exists, skips (returns nil) - If
AutoApplyis true, also sets to system environment
err := loader.Set("CUSTOM_KEY", "value")
if err != nil {
// Handle error
}Error Types:
*ValidationError- Invalid key name format (Field="key")*SecurityError- Forbidden key (matchable viaerrors.Is(err, env.ErrSecurityViolation))ErrInvalidValue- Invalid value (whenValidateValuesis true, value contains unsafe content like null bytes or control characters)ErrClosed- Loader is closed
Delete
func (l *Loader) Delete(key string) errorDeletes an environment variable.
Parameters:
key- Key name
Returns:
error- Deletion error
Behavior:
- If the variable has been applied to the system environment, also deletes from 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- List of key names; returns nil if the 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 the 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- Number of variables; returns 0 if the 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- Application error
Behavior:
- Iterates through all loaded variables
- Whether to overwrite existing system environment variables is controlled by
OverwriteExistingconfiguration - After applying, values can be accessed via
os.Getenv()
Error types:
ErrClosed- Loader has been closed- Wrapped
oserror - Failed to set environment variable (key name masked; sensitive key not exposed in error message)
err := loader.Apply()
if err != nil {
panic(err)
}
// After applying, os.Getenv() also has access
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 not 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)
Note
The returned Config should be treated as read-only. Modifying KeyPattern, AllowedKeys, ForbiddenKeys, RequiredKeys and other fields may affect loader behavior. For a safe mutable copy, manually copy the needed fields.
cfg := loader.Config()
fmt.Printf("Max file size: %d\n", cfg.MaxFileSize)Validation and Mapping
Validate
func (l *Loader) Validate() errorValidates that all required keys exist.
Returns:
error- Validation error
Behavior:
- Checks whether 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 key
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- Pointer to a struct
Returns:
error- Mapping error
Supported Tags:
env:"KEY"- Specifies the environment variable nameenv:"-"- Ignores this fieldenvDefault:"value"- Specifies the default value
Slice fields are split by comma , by default (surrounding whitespace around the separator is trimmed automatically); 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- Closing error
Behavior:
- Securely zeroes 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...Behavior After Close
After closing, all operations will return errors or zero values:
LoadFiles->ErrClosedGetString-> Returns empty valueSet->ErrClosedKeys-> Returns nilLen-> Returns 0
IsClosed
func (l *Loader) IsClosed() boolChecks whether the loader is closed.
Returns:
bool- Whether closed
if loader.IsClosed() {
// Loader is 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("Config 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