Home

Awesome

Envconfig

GoDoc

Envconfig populates struct field values based on environment variables or arbitrary lookup functions. It supports pre-setting mutations, which is useful for things like converting values to uppercase, trimming whitespace, or looking up secrets.

Usage

Define a struct with fields using the env tag:

type MyConfig struct {
  Port     string `env:"PORT"`
  Username string `env:"USERNAME"`
}

Set some environment variables:

export PORT=5555
export USERNAME=yoyo

Process it using envconfig:

package main

import (
  "context"
  "log"

  "github.com/sethvargo/go-envconfig"
)

func main() {
  ctx := context.Background()

  var c MyConfig
  if err := envconfig.Process(ctx, &c); err != nil {
    log.Fatal(err)
  }

  // c.Port = 5555
  // c.Username = "yoyo"
}

You can also use nested structs, just remember that any fields you want to process must be public:

type MyConfig struct {
  Database *DatabaseConfig
}

type DatabaseConfig struct {
  Port     string `env:"PORT"`
  Username string `env:"USERNAME"`
}

Configuration

Use the env struct tag to define configuration. See the godoc for usage examples.

Decoding

[!NOTE]

Complex types are only decoded or unmarshalled when the environment variable is defined or a default value is specified.

Durations

In the environment, time.Duration values are specified as a parsable Go duration:

type MyStruct struct {
  MyVar time.Duration `env:"MYVAR"`
}
export MYVAR="10m" # 10 * time.Minute

TextUnmarshaler / BinaryUnmarshaler

Types that implement TextUnmarshaler or BinaryUnmarshaler are processed as such.

json.Unmarshaler

Types that implement json.Unmarshaler are processed as such.

gob.Decoder

Types that implement gob.Decoder are processed as such.

Slices

Slices are specified as comma-separated values.

type MyStruct struct {
  MyVar []string `env:"MYVAR"`
}
export MYVAR="a,b,c,d" # []string{"a", "b", "c", "d"}

Note that byte slices are special cased and interpreted as strings from the environment.

Maps

Maps are specified as comma-separated key:value pairs:

type MyStruct struct {
  MyVar map[string]string `env:"MYVAR"`
}
export MYVAR="a:b,c:d" # map[string]string{"a":"b", "c":"d"}

Structs

Envconfig walks the entire struct, including nested structs, so deeply-nested fields are also supported.

If a nested struct is a pointer type, it will automatically be instantianted to the non-nil value. To change this behavior, see Initialization.

Custom Decoders

You can also define your own decoders. See the godoc for more information.

Testing

Relying on the environment in tests can be troublesome because environment variables are global, which makes it difficult to parallelize the tests. Envconfig supports extracting data from anything that returns a value:

lookuper := envconfig.MapLookuper(map[string]string{
  "FOO": "bar",
  "ZIP": "zap",
})

var config Config
envconfig.ProcessWith(ctx, &envconfig.Config{
  Target:   &config,
  Lookuper: lookuper,
})

Now you can parallelize all your tests by providing a map for the lookup function. In fact, that's how the tests in this repo work, so check there for an example.

You can also combine multiple lookupers with MultiLookuper. See the GoDoc for more information and examples.