Manage your application config as a typesafe struct in as little as two function calls.
type MyConfig struct {
DatabaseUrl string `config:"DATABASE_URL"`
FeatureFlag bool `config:"FEATURE_FLAG"`
Port int // tags are optional. PORT is assumed
...
}
var c MyConfig
err := config.FromEnv().To(&c)It's just simple, pure stdlib.
-
A field's type determines what strconv function is called.
-
All string conversion rules are as defined in the strconv package
-
time.Durationfollows the same parsing rules as time.ParseDuration -
*url.URLfollows the same parsing rules as url.Parse- NOTE:
*url.URLfields on the struct must be a pointer
- NOTE:
-
Any type implementing encoding.TextUnmarshaler is parsed with its
UnmarshalTextmethod, e.g.time.Time,netip.Addr,net.IP,slog.Level, or your own types -
If chaining multiple data sources, data sets are merged. Later values override previous values.
config.From("dev.config").FromEnv().To(&c)
-
Unset values remain intact or as their native zero value
-
Nested structs/subconfigs are delimited with double underscore
- e.g.
PARENT__CHILD
- e.g.
-
Env vars map to struct fields case insensitively
- NOTE: Also true when using struct tags.
-
Any errors encountered are aggregated into a single
*config.Error- inspect it with
errors.AsType[*config.Error](err), or test causes witherrors.Is(e.g.fs.ErrNotExist,strconv.ErrRange) - errors never contain configured values, so they are safe to log
- the entirety of the struct is always attempted
- failed conversions (i.e. converting "x" to an int) and file i/o are the only sources of errors
- missing values are not errors
- inspect it with
- It's the cloud-native way to manage config. See 12 Factor Apps
- Simple:
- only 2 lines to configure.
- Composeable:
- Merge local files and environment variables for effortless local development.
- small:
- only stdlib
Opinionated and narrow in scope. This library is only meant to do config binding. Feel free to use it on its own, or alongside other libraries.
-
Only structs at the entry point. This keeps the API surface small.
-
Slices are space delimited. This matches how environment variables and commandline args are handled by the
gocmd. -
No slices of structs. The extra complexity isn't warranted for such a niche usecase.
-
No maps. The only feature of maps not handled by structs for this usecase is dynamic keys.
-
No pointer members. If you really need one, just take the address of parts of your struct.
- One exception is
*url.URL, which is explicitly a pointer for ease of use, matching theurlpackage conventions
- One exception is