Documentation ¶
Overview ¶
Package env provides an API for loading environment variables into structs. See the Load function documentation for details.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrEmptyTagName = errors.New("env: empty tag name is not allowed")
ErrEmptyTagName is returned when the `env` tag is found but the name of the environment variable is empty.
var ErrInvalidArgument = errors.New("env: argument must be a non-nil struct pointer")
ErrInvalidArgument is returned when the argument provided to Load/LoadFrom is invalid.
var ErrInvalidTagOption = errors.New("env: invalid tag option")
ErrInvalidTagOption is returned when the `env` tag contains an invalid option, e.g. `env:"VAR,invalid"`.
var ErrUnsupportedType = errors.New("env: unsupported type")
ErrUnsupportedType is returned when the provided struct contains a field of an unsupported type.
var Usage = func(w io.Writer, vars []Var) { tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0) defer tw.Flush() fmt.Fprintf(tw, "Usage:\n") for _, v := range vars { fmt.Fprintf(tw, "\t%s\t%s", v.Name, v.Type) if v.Required { fmt.Fprintf(tw, "\trequired") } else { if v.Type.Kind() == reflect.String && v.Default == "" { v.Default = "<empty>" } fmt.Fprintf(tw, "\tdefault %s", v.Default) } if v.Desc != "" { fmt.Fprintf(tw, "\t%s", v.Desc) } fmt.Fprintf(tw, "\n") } }
Usage prints a usage message documenting all defined environment variables. It will be called by Load/LoadFrom if the WithUsageOnError option is provided and an error occurs while loading environment variables. It is exported as a variable, so it can be changed to a custom implementation.
Functions ¶
func Load ¶
Load loads environment variables into the provided struct using the OS Provider as their source. To specify a custom Provider, use the LoadFrom function. dst must be a non-nil struct pointer, otherwise Load returns ErrInvalidArgument.
The struct fields must have the `env:"VAR"` struct tag, where VAR is the name of the corresponding environment variable. Unexported fields and fields without this tag (except nested structs) are ignored. If the tag is found but the name of the environment variable is empty, the error will be ErrEmptyTagName.
The following types are supported as struct fields:
- int (any kind)
- float (any kind)
- bool
- string
- time.Duration
- encoding.TextUnmarshaler
- slices of any type above (space is the default separator for values)
See the strconv package from the standard library for parsing rules. Implementing the encoding.TextUnmarshaler interface is enough to use any user-defined type. Default values can be specified either using the `default` struct tag (has a higher priority) or by initializing the struct fields directly. Nested structs of any depth level are supported, but only non-struct fields are considered as targets for parsing. If a field of an unsupported type is found, the error will be ErrUnsupportedType.
The name of the environment variable can be followed by comma-separated options in the form of `env:"VAR,option1,option2,..."`. The following tag-level options are supported:
- required: marks the environment variable as required
- expand: expands the value of the environment variable using os.Expand
If environment variables are marked as required but not set, an error of type NotSetError will be returned. If the tag contains an invalid option, the error will be ErrInvalidTagOption.
In addition to the tag-level options, Load also supports the following function-level options:
- WithPrefix: sets prefix for each environment variable
- WithSliceSeparator: sets custom separator to parse slice values
- WithStrictMode: enables strict mode: no `default` tag == required
- WithUsageOnError: enables a usage message printing when an error occurs
See their documentation for details.
Example ¶
package main import ( "fmt" "os" "github.com/junk1tm/env" ) func main() { os.Setenv("PORT", "8080") var cfg struct { Port int `env:"PORT"` } if err := env.Load(&cfg); err != nil { // handle error } fmt.Println(cfg.Port) // 8080 }
Output:
Example (DefaultValue) ¶
package main import ( "fmt" "github.com/junk1tm/env" ) func main() { cfg := struct { Host string `env:"HOST" default:"localhost"` // either use the `default` tag... Port int `env:"PORT"` }{ Port: 8080, // ...or initialize the struct field directly. } if err := env.Load(&cfg); err != nil { // handle error } fmt.Println(cfg.Host) // localhost fmt.Println(cfg.Port) // 8080 }
Output:
Example (Expand) ¶
package main import ( "fmt" "os" "github.com/junk1tm/env" ) func main() { os.Setenv("PORT", "8080") os.Setenv("ADDR", "localhost:${PORT}") var cfg struct { Addr string `env:"ADDR,expand"` } if err := env.Load(&cfg); err != nil { // handle error } fmt.Println(cfg.Addr) // localhost:8080 }
Output:
Example (NestedStruct) ¶
package main import ( "fmt" "os" "github.com/junk1tm/env" ) func main() { os.Setenv("HTTP_PORT", "8080") var cfg struct { HTTP struct { Port int `env:"HTTP_PORT"` } } if err := env.Load(&cfg); err != nil { // handle error } fmt.Println(cfg.HTTP.Port) // 8080 }
Output:
Example (Required) ¶
package main import ( "errors" "fmt" "github.com/junk1tm/env" ) func main() { // os.Setenv("HOST", "localhost") // os.Setenv("PORT", "8080") var cfg struct { Host string `env:"HOST,required"` Port int `env:"PORT,required"` } if err := env.Load(&cfg); err != nil { var notSetErr *env.NotSetError if errors.As(err, ¬SetErr) { fmt.Println(notSetErr.Names) // [HOST PORT] } } }
Output:
func LoadFrom ¶
LoadFrom loads environment variables into the provided struct using the specified Provider as their source. See Load documentation for more details.
Example ¶
package main import ( "fmt" "github.com/junk1tm/env" ) func main() { m := env.Map{"PORT": "8080"} var cfg struct { Port int `env:"PORT"` } if err := env.LoadFrom(m, &cfg); err != nil { // handle error } fmt.Println(cfg.Port) // 8080 }
Output:
Types ¶
type NotSetError ¶
type NotSetError struct { // Names is a slice of the names of the missing required environment // variables. Names []string }
NotSetError is returned when environment variables are marked as required but not set.
func (*NotSetError) Error ¶
func (e *NotSetError) Error() string
Error implements the error interface.
type Option ¶
type Option func(*loader)
Option allows to customize the behaviour of the Load/LoadFrom functions.
func WithPrefix ¶
WithPrefix configures Load/LoadFrom to automatically add the provided prefix to each environment variable. By default, no prefix is configured.
Example ¶
package main import ( "fmt" "os" "github.com/junk1tm/env" ) func main() { os.Setenv("APP_PORT", "8080") var cfg struct { Port int `env:"PORT"` } if err := env.Load(&cfg, env.WithPrefix("APP_")); err != nil { // handle error } fmt.Println(cfg.Port) // 8080 }
Output:
func WithSliceSeparator ¶
WithSliceSeparator configures Load/LoadFrom to use the provided separator when parsing slice values. The default one is space.
Example ¶
package main import ( "fmt" "os" "github.com/junk1tm/env" ) func main() { os.Setenv("PORTS", "8080;8081;8082") var cfg struct { Ports []int `env:"PORTS"` } if err := env.Load(&cfg, env.WithSliceSeparator(";")); err != nil { // handle error } fmt.Println(cfg.Ports[0]) // 8080 fmt.Println(cfg.Ports[1]) // 8081 fmt.Println(cfg.Ports[2]) // 8082 }
Output:
func WithStrictMode ¶ added in v0.5.0
func WithStrictMode() Option
WithStrictMode configures Load/LoadFrom to treat all environment variables without the `default` tag as required. By default, strict mode is disabled.
Example ¶
package main import ( "errors" "fmt" "github.com/junk1tm/env" ) func main() { // os.Setenv("HOST", "localhost") var cfg struct { Host string `env:"HOST"` // (required) Port int `env:"PORT" default:"8080"` } if err := env.Load(&cfg, env.WithStrictMode()); err != nil { var notSetErr *env.NotSetError if errors.As(err, ¬SetErr) { fmt.Println(notSetErr.Names) // [HOST] } } }
Output:
func WithUsageOnError ¶ added in v0.3.0
WithUsageOnError configures Load/LoadFrom to write an auto-generated usage message to the provided io.Writer, if an error occurs while loading environment variables. The message format can be changed by assigning the global Usage variable to a custom implementation.
Example ¶
package main import ( "os" "time" "github.com/junk1tm/env" ) func main() { // os.Setenv("DB_HOST", "localhost") // os.Setenv("DB_PORT", "5432") cfg := struct { DB struct { Host string `env:"DB_HOST,required" desc:"database host"` Port int `env:"DB_PORT,required" desc:"database port"` } HTTPPort int `env:"HTTP_PORT" desc:"http server port"` Timeouts []time.Duration `env:"TIMEOUTS" desc:"timeout steps"` }{ HTTPPort: 8080, Timeouts: []time.Duration{1 * time.Second, 2 * time.Second, 3 * time.Second}, } if err := env.Load(&cfg, env.WithUsageOnError(os.Stdout)); err != nil { // handle error } }
Output: Usage: DB_HOST string required database host DB_PORT int required database port HTTP_PORT int default 8080 http server port TIMEOUTS []time.Duration default [1s 2s 3s] timeout steps
type Provider ¶
type Provider interface { // LookupEnv retrieves the value of the environment variable named by the // key. If it is not found, the boolean will be false. LookupEnv(key string) (value string, ok bool) }
Provider represents an entity that is able to provide environment variables.
var OS Provider = ProviderFunc(os.LookupEnv)
OS is the main Provider that uses os.LookupEnv.
func MultiProvider ¶ added in v0.7.0
MultiProvider combines multiple providers into a single one, which will contain the union of their environment variables. The order of the providers matters: if the same key exists in more than one provider, the value from the last one will be used.
Example ¶
package main import ( "fmt" "os" "github.com/junk1tm/env" ) func main() { os.Setenv("HOST", "localhost") p := env.MultiProvider( env.OS, env.Map{"PORT": "8080"}, ) var cfg struct { Host string `env:"HOST,required"` Port int `env:"PORT,required"` } if err := env.LoadFrom(p, &cfg); err != nil { // handle error } fmt.Println(cfg.Host) // localhost fmt.Println(cfg.Port) // 8080 }
Output:
type ProviderFunc ¶
ProviderFunc is an adapter that allows using functions as Provider.
type Var ¶ added in v0.3.0
type Var struct { Name string // Name is the full name of the variable, including prefix. Type reflect.Type // Type is the variable's type. Desc string // Desc is an optional description parsed from the `desc` tag. Default string // Default is the default value of the variable. If the variable is marked as required, it will be empty. Required bool // Required is true, if the variable is marked as required. Expand bool // Expand is true, if the variable is marked to be expanded with [os.Expand]. // contains filtered or unexported fields }
Var contains information about the environment variable parsed from a struct field. It is exported as a part of the Usage function signature.
Directories ¶
Path | Synopsis |
---|---|
Package assert provides common assertions to use with the standard testing package.
|
Package assert provides common assertions to use with the standard testing package. |
dotimport
Package dotimport provides type aliases for the parent [assert] package.
|
Package dotimport provides type aliases for the parent [assert] package. |