Tiny-but-mighty environment reader and struct binder for Go.
- Zero deps, stdlib only.
- Typed getters: bool, int, float64, duration, URL, IP, slices.
- Struct binding with tags, defaults, and JSON decode.
${VAR}and${VAR:-def}expansion.- Pluggable sources (env + maps + composites).
- Lazy getters and safe redacted dumps.
- Optional hooks for metrics/tracing without adding deps.
go get github.com/aatuh/envvar/v2Check the examples from the examples package.
Run examples with:
go test -v -count 1 ./examples
# Run specific example.
go test -v -count 1 ./examples -run TestBasicGettersGet,GetOr,MustGetGetBool,GetInt,GetFloat64,GetDurationGetURL,GetIP,GetStringSlice(+GetStringSliceSep)- Generic:
GetTyped[T](key, conv) - All have
Must*andOrvariants where it makes sense.
${NAME}and${NAME:-default}are expanded in values read from env and when usingExpandMap.
Cache-on-first-use helpers, e.g. LazyBool("DEBUG")().
Populate a struct from environment with tags:
env:"NAME[,required]"choose the env var name and requiredness.envdef:"value"default used if missing.envsep:","separator for[]string(default ",").envjson:"true"JSON decode into field type (maps, slices, structs).
Pointer fields are allocated automatically.
Try a prefixed variable first, then fall back to the base name:
// Tries MYAPP_PORT first, then PORT.
envvar.MustBindWithPrefix(&cfg, "MYAPP_")By default, getters and Bind read from process environment variables.
You can also load from files using LoadEnvVars:
// Load from specific files
if err := envvar.LoadEnvVars([]string{"./.env.local", "./.env"}); err != nil {
// handle error
}
// Or use the default paths (.env, then /env/.env)
envvar.MustLoadEnvVars(nil)
port := envvar.MustGetInt("PORT") // reads from loaded env varsExpand ${VAR} and ${VAR:-def} inside a map, using map values first,
then process environment variables:
in := map[string]string{
"HOST": "db.local",
"DSN": "postgres://${HOST}:${PORT:-5432}/app",
}
out := envvar.MustExpandMap(in)
// out["DSN"] == "postgres://db.local:5432/app"// Try custom locations in order:
if err := envvar.LoadEnvVars([]string{"./.env.local", "./.env"}); err != nil {
// handle error
}log.Printf("env: %#v", envvar.DumpRedacted())Heuristics redact keys containing SECRET, TOKEN, PASSWORD, or
suffix _KEY.
- All binding errors are aggregated and returned as a
MultiError. - Missing required fields are reported clearly.
type myHook struct{}
func (myHook) OnLoad(src string, keys int) {}
func (myHook) OnGet(k string, ok bool, err error, d time.Duration) {}
envvar.SetHook(myHook{})