Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/go-simpler/env
🔍 Load environment variables into a config struct
https://github.com/go-simpler/env
12factor configuration dependency-free environment-variables go library
Last synced: 13 days ago
JSON representation
🔍 Load environment variables into a config struct
- Host: GitHub
- URL: https://github.com/go-simpler/env
- Owner: go-simpler
- License: mpl-2.0
- Created: 2022-01-10T17:28:03.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-04-17T19:31:57.000Z (7 months ago)
- Last Synced: 2024-04-22T15:20:33.459Z (7 months ago)
- Topics: 12factor, configuration, dependency-free, environment-variables, go, library
- Language: Go
- Homepage: https://go-simpler.org/env
- Size: 85.9 KB
- Stars: 53
- Watchers: 2
- Forks: 4
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-go - env - A lightweight package for loading environment variables into structs. (Configuration / Standard CLI)
README
![logo](logo.svg)
🔍 Load environment variables into a config struct
[![awesome-go](https://awesome.re/badge.svg)](https://github.com/avelino/awesome-go#configuration)
[![checks](https://github.com/go-simpler/env/actions/workflows/checks.yml/badge.svg)](https://github.com/go-simpler/env/actions/workflows/checks.yml)
[![pkg.go.dev](https://pkg.go.dev/badge/go-simpler.org/env.svg)](https://pkg.go.dev/go-simpler.org/env)
[![goreportcard](https://goreportcard.com/badge/go-simpler.org/env)](https://goreportcard.com/report/go-simpler.org/env)
[![codecov](https://codecov.io/gh/go-simpler/env/branch/main/graph/badge.svg)](https://codecov.io/gh/go-simpler/env)## 📌 About
This package is made for apps that [store config in environment variables][1].
Its purpose is to replace fragmented `os.Getenv` calls in `main.go` with a single struct definition,
which simplifies config management and improves code readability.## 🚀 Features
* Support for all common types and user-defined types
* Configurable [source](#source) of environment variables
* Options: [required](#required), [expand](#expand), [slice separator](#slice-separator), [name separator](#name-separator)
* Auto-generated [usage message](#usage-message)## 📦 Install
Go 1.20+
```shell
go get go-simpler.org/env
```## 📋 Usage
`Load` is the main function of the package.
It loads environment variables into the given struct.The struct fields must have the `env:"VAR"` struct tag,
where `VAR` is the name of the corresponding environment variable.
Unexported fields are ignored.```go
os.Setenv("PORT", "8080")var cfg struct {
Port int `env:"PORT"`
}
if err := env.Load(&cfg, nil); err != nil {
fmt.Println(err)
}fmt.Println(cfg.Port) // 8080
```### Supported types
* `int` (any kind)
* `float` (any kind)
* `bool`
* `string`
* `time.Duration`
* `encoding.TextUnmarshaler`
* slices of any type above
* nested structs of any depthSee the `strconv.Parse*` functions for the parsing rules.
User-defined types can be used by implementing the `encoding.TextUnmarshaler` interface.### Nested structs
Nested struct of any depth level are supported,
allowing grouping of related environment variables.```go
os.Setenv("DB_HOST", "localhost")
os.Setenv("DB_PORT", "5432")var cfg struct {
DB struct {
Host string `env:"DB_HOST"`
Port int `env:"DB_PORT"`
}
}
if err := env.Load(&cfg, nil); err != nil {
fmt.Println(err)
}fmt.Println(cfg.DB.Host) // localhost
fmt.Println(cfg.DB.Port) // 5432
```If a nested struct has the optional `env:"PREFIX"` tag,
the environment variables declared by its fields are prefixed with `PREFIX`.```go
os.Setenv("DB_HOST", "localhost")
os.Setenv("DB_PORT", "5432")var cfg struct {
DB struct {
Host string `env:"HOST"`
Port int `env:"PORT"`
} `env:"DB_"`
}
if err := env.Load(&cfg, nil); err != nil {
fmt.Println(err)
}fmt.Println(cfg.DB.Host) // localhost
fmt.Println(cfg.DB.Port) // 5432
```### Default values
Default values can be specified using the `default:"VALUE"` struct tag.
```go
os.Unsetenv("PORT")var cfg struct {
Port int `env:"PORT" default:"8080"`
}
if err := env.Load(&cfg, nil); err != nil {
fmt.Println(err)
}fmt.Println(cfg.Port) // 8080
```### Required
Use the `required` option to mark an environment variable as required.
If it is not set, an error of type `NotSetError` is returned.```go
os.Unsetenv("PORT")var cfg struct {
Port int `env:"PORT,required"`
}
if err := env.Load(&cfg, nil); err != nil {
var notSetErr *env.NotSetError
if errors.As(err, ¬SetErr) {
fmt.Println(notSetErr) // env: PORT is required but not set
}
}
```### Expand
Use the `expand` option to automatically expand the value of an environment variable using `os.Expand`.
```go
os.Setenv("PORT", "8080")
os.Setenv("ADDR", "localhost:${PORT}")var cfg struct {
Addr string `env:"ADDR,expand"`
}
if err := env.Load(&cfg, nil); err != nil {
fmt.Println(err)
}fmt.Println(cfg.Addr) // localhost:8080
```### Slice separator
Space is the default separator used to parse slice values.
It can be changed with `Options.SliceSep`.```go
os.Setenv("PORTS", "8080,8081,8082")var cfg struct {
Ports []int `env:"PORTS"`
}
if err := env.Load(&cfg, &env.Options{SliceSep: ","}); err != nil {
fmt.Println(err)
}fmt.Println(cfg.Ports) // [8080 8081 8082]
```### Name separator
By default, environment variable names are concatenated from nested struct tags as is.
If `Options.NameSep` is not empty, it is used as the separator.```go
os.Setenv("DB_HOST", "localhost")
os.Setenv("DB_PORT", "5432")var cfg struct {
DB struct {
Host string `env:"HOST"`
Port int `env:"PORT"`
} `env:"DB"`
}
if err := env.Load(&cfg, &env.Options{NameSep: "_"}); err != nil {
fmt.Println(err)
}fmt.Println(cfg.DB.Host) // localhost
fmt.Println(cfg.DB.Port) // 5432
```### Source
By default, `Load` retrieves environment variables directly from OS.
To use a different source, pass an implementation of the `Source` interface via `Options.Source`.```go
type Source interface {
LookupEnv(key string) (value string, ok bool)
}
```Here's an example of using `Map`, a `Source` implementation useful in tests.
```go
m := env.Map{"PORT": "8080"}var cfg struct {
Port int `env:"PORT"`
}
if err := env.Load(&cfg, &env.Options{Source: m}); err != nil {
fmt.Println(err)
}fmt.Println(cfg.Port) // 8080
```### Usage message
The `Usage` function prints a usage message documenting all defined environment variables.
An optional usage string can be added to environment variables with the `usage:"STRING"` struct tag.```go
os.Unsetenv("DB_HOST")
os.Unsetenv("DB_PORT")var cfg struct {
DB struct {
Host string `env:"DB_HOST,required" usage:"database host"`
Port int `env:"DB_PORT,required" usage:"database port"`
}
HTTPPort int `env:"HTTP_PORT" default:"8080" usage:"http server port"`
}
if err := env.Load(&cfg, nil); err != nil {
fmt.Println(err)
fmt.Println("Usage:")
env.Usage(&cfg, os.Stdout, nil)
}
``````
Usage:
DB_HOST string required database host
DB_PORT int required database port
HTTP_PORT int default 8080 http server port
```The format of the message can be customized by implementing the `Usage([]env.Var, io.Writer, *env.Options)` method.
```go
type Config struct{ ... }func (Config) Usage(vars []env.Var, w io.Writer, opts *env.Options) {
for v := range vars {
// write to w.
}
}
```[1]: https://12factor.net/config