simpleenv maps environment variables into a Go struct and validates values using env struct tags.
go get github.com/edgarsilva/simpleenvgo get github.com/edgarsilva/simpleenv@v1.3.0
go mod tidyTo verify the resolved version:
go list -m github.com/edgarsilva/simpleenv- Added
minlenandmaxlenforstringandencoding.TextUnmarshalerfields. - String length checks use Unicode rune count.
minlenandmaxlenare invalid for numeric, boolean, and duration fields.
- Added
trimspaceforstringandencoding.TextUnmarshalerfields to explicitly trim leading/trailing whitespace before validation and parsing. trimspaceis invalid for numeric, boolean, and duration fields.- Numeric and duration parsing/constraints remain strict; whitespace in values is not trimmed automatically.
- Tagged env vars now fail when present with an empty value (
KEY=) by default. - If empty values are intentional, add
allowemptytostringorencoding.TextUnmarshalerfields. allowemptyis invalid for numeric, boolean, and duration fields.
package main
import (
"log"
"github.com/edgarsilva/simpleenv"
)
type AppEnv struct {
Environment string `env:"ENVIRONMENT;oneof=development,test,staging,production"`
Version float64 `env:"VERSION;optional"`
APIURL string `env:"API_URL;format=URL"`
Concurrency int `env:"CONCURRENCY;min=1;max=32"`
// No env tag: ignored by simpleenv (useful for defaults/derived values).
ServiceName string
}
func main() {
cfg := AppEnv{ServiceName: "my-service"}
if err := simpleenv.Load(&cfg); err != nil {
log.Fatal(err)
}
}Tag format is:
env:"ENV_KEY;constraint1;constraint2"
Examples:
env:"PORT;min=1;max=65535"env:"MODE;oneof=dev,test,prod"env:"PUBSUB_URL;regex='(http|https)://(localhost|127.0.0.1):[0-9]+'"
stringboolintint64uintfloat64time.Duration- custom types implementing
encoding.TextUnmarshaler
optional: allows env var to be missing.- Missing optional env vars keep whatever value was already in the struct (or zero value if it started empty).
allowempty: only forstringorencoding.TextUnmarshalerfields; allowsMY_ENV_VAR=when the key exists.trimspace: only forstringorencoding.TextUnmarshalerfields; trims leading/trailing whitespace before validation/parsing.minlen=n: only forstringorencoding.TextUnmarshalerfields; value length must be>= nmaxlen=n: only forstringorencoding.TextUnmarshalerfields; value length must be<= noneof=a,b,c: value must match one optionmin=n: numeric value must be>= n(fortime.Duration, use duration values like500ms,2s,1m)max=n: numeric value must be<= n(fortime.Duration, use duration values like500ms,2s,1m)regex=pattern: value must match regex (single or double quoted patterns are supported)format=...: value must match one of the supported formats below
URL: validhttp/httpsURLURI: valid URI with a schemeFILE: existing file pathDIR: existing directory pathHOSTPORT: validhost:portvalueUUID: valid UUID (canonical hyphenated form)IP: valid IPv4 or IPv6 addressHEX: hexadecimal string (0-9,a-f,A-F)ALPHANUMERIC: letters and numbers onlyIDENTIFIER: letters, numbers,_, and-only
Note: only one format value is allowed (format=URL is valid, format=URL|FILE is rejected).
Loadrequires a pointer to a struct:simpleenv.Load(&cfg).- Fields without an
envtag are skipped. optionalapplies only when the env var is missing, not when it is empty (MY_ENV_VAR=).- By default, if a tagged env var is present but empty (
MY_ENV_VAR=),Loadreturns an error. trimspaceis explicit (not automatic), and only applies when the tag is present.trimspaceruns beforeallowempty,oneof,minlen,maxlen,regex, andformatchecks.- Use
allowemptyonly forstringorencoding.TextUnmarshalerfields when empty values are intentional. allowempty,trimspace,minlen, andmaxlenare invalid for numeric, boolean, and duration fields; useoptionalwhen the env var may be missing.- Unknown constraints return an error.
- Unknown
format=values return an error.
Validation/parse errors include field name, env key, invalid value, and expectation:
invalid value for field "Concurrency" from ENV["CONCURRENCY"]: got "abc", expected a valid int