File Format
The env library supports multiple configuration file formats: .env, JSON, and YAML.
.env Format
Basic Syntax
# Comment
KEY=value
# Equals sign in value
URL=https://example.com?foo=bar
# Blank lines are ignored
# Invalid: key cannot contain spaces
# MY KEY=valueQuoting
# Double quotes: preserve spaces, support escaping
MESSAGE="Hello World"
PATH="/usr/local/bin"
# Single quotes: do not process escapes (preserve backslash sequences as-is)
# Note: single quotes do NOT prevent variable expansion — expansion happens after quote stripping
LITERAL='no escaping here: \n stays literal'
# Unquoted
SIMPLE=value
# Empty values
EMPTY=
EMPTY=""
EMPTY=''Escape Characters
Escaping is supported within double quotes:
# Newline
MULTILINE="line1\nline2"
# Tab
TABBED="col1\tcol2"
# Quotes
QUOTED="He said \"Hello\""
# Backslash
PATH="C:\\Users\\name"
# Dollar sign
PRICE="Price: \$100"Variable Expansion
Supported when ExpandVariables is enabled:
# Reference other variables
BASE_URL=https://api.example.com
API_URL=${BASE_URL}/v1
# Simple syntax
URL=$BASE_URL/path
# Default values
HOST=${HOST:-localhost}
PORT=${PORT:-8080}
# Nested expansion
SERVICE=${CLUSTER:-default}-${REGION:-us-east}export Syntax
Supported when AllowExportPrefix is enabled:
# Bash-style export
export KEY=value
export ANOTHER="quoted value"YAML-Style Syntax
Supported when AllowYamlSyntax is enabled:
# YAML-style key-value pairs
KEY: value
ANOTHER: "quoted value"Multiline Values
The .env parser scans line by line, parsing each line independently and not supporting quoted strings that span multiple lines — a double-quoted value must be closed on the same line, otherwise it returns ErrInvalidValue. To include newlines, use the \n escape (only effective within double quotes; single quotes do not process escapes):
# \n inside double quotes is parsed as a newline
LINES="line1\nline2\nline3"
# The actual value is three lines: line1 / line2 / line3
# For multi-line certificates like PRIVATE_KEY, join with \n
PRIVATE_KEY="-----BEGIN KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...\n-----END KEY-----"For genuinely cross-line strings, use the JSON or YAML format instead, or extend multi-line support via a custom parser.
JSON Format
Basic Structure
{
"APP_NAME": "my-app",
"APP_VERSION": "1.0.0",
"DEBUG": true,
"PORT": 8080
}Nested Objects
Nested objects are flattened:
{
"database": {
"host": "localhost",
"port": 5432
}
}Result:
DATABASE_HOST=localhost
DATABASE_PORT=5432Arrays
Arrays are flattened into indexed keys:
{
"ALLOWED_HOSTS": ["localhost", "example.com"],
"PORTS": [80, 443, 8080]
}Result:
ALLOWED_HOSTS_0=localhost
ALLOWED_HOSTS_1=example.com
PORTS_0=80
PORTS_1=443
PORTS_2=8080Accessing Array Elements
Use the GetSlice[T] function or dot-notation paths to access indexed keys:
hosts := env.GetSlice[string]("ALLOWED_HOSTS")
port0 := env.GetInt("PORTS_0") // 80See GetSlice documentation for details.
Type Conversion Options
cfg := env.DefaultConfig()
// Convert null to empty string
cfg.JSONNullAsEmpty = true
// Convert numbers to strings
cfg.JSONNumberAsString = true
// Convert booleans to strings
cfg.JSONBoolAsString = trueDepth Limit
cfg.JSONMaxDepth = 10 // Maximum nesting depthYAML Format
Basic Structure
APP_NAME: my-app
APP_VERSION: "1.0.0"
DEBUG: true
PORT: 8080Nested Structures
database:
host: localhost
port: 5432
credentials:
user: admin
password: secretFlattened result:
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_CREDENTIALS_USER=admin
DATABASE_CREDENTIALS_PASSWORD=secretLists
Lists are flattened into indexed keys:
allowed_hosts:
- localhost
- example.com
- api.example.comResult:
ALLOWED_HOSTS_0=localhost
ALLOWED_HOSTS_1=example.com
ALLOWED_HOSTS_2=api.example.comMultiline Strings
Note
YAML block scalars (literal block | and folded block >) are not currently supported. The parser treats |/> as ordinary scalar characters and the subsequent indented lines break the key-value parsing.
For values that must preserve newlines, use double quotes with \n escapes:
description: "Line1\nLine2\nLine3"Or extend block scalar support via a custom parser.
Type Conversion Options
cfg := env.DefaultConfig()
cfg.YAMLNullAsEmpty = true
cfg.YAMLNumberAsString = true
cfg.YAMLBoolAsString = true
cfg.YAMLMaxDepth = 10Format Detection
Auto-Detection
// Detect by extension
format := env.DetectFormat("config.json") // FormatJSON
format = env.DetectFormat("settings.yaml") // FormatYAML
format = env.DetectFormat(".env") // FormatEnv
// Returns FormatAuto when no matching extension (defaults to .env parser)
format = env.DetectFormat("config") // FormatAutoFormat Constants
const (
FormatAuto FileFormat = iota // Auto-detect
FormatEnv // .env format
FormatJSON // JSON format
FormatYAML // YAML format
)Format String
format := env.FormatJSON
fmt.Println(format.String()) // Output: jsonBest Practices
Choosing a Format
| Scenario | Recommended Format |
|---|---|
| Simple configuration | .env |
| Complex nested configuration | JSON or YAML |
| Sharing with other tools | JSON |
| Human readability priority | YAML |
| Docker/K8s environments | .env |
File Naming
.env # Default configuration
.env.local # Local overrides (not committed)
.env.development # Development environment
.env.staging # Staging environment
.env.production # Production environment
.env.test # Test environmentMixed Usage
// You can mix different formats
loader.LoadFiles(
"base.env", // Base configuration
"database.json", // Database configuration
"secrets.yaml", // Sensitive configuration
".env.local", // Local overrides
)Git Ignore
# Ignore sensitive configuration
.env.local
.env.*.local
.env.production
secrets.yaml
# Keep templates
!.env.exampleRelated Documentation
- Multi-Format Configuration - Multi-format loading guide
- ComponentFactory API - DetectFormat function reference
- Config API - JSON/YAML parsing options