Documentation ¶
Overview ¶
Package env is a simple, zero-dependencies library to parse environment variables into structs.
Example:
type config struct { Home string `env:"HOME"` } // parse var cfg config err := env.Parse(&cfg) // or parse with generics cfg, err := env.ParseAs[config]()
Check the examples and README for more detailed usage.
Example ¶
Basic package usage example.
type Config struct { Foo string `env:"FOO"` } os.Setenv("FOO", "bar") // parse: var cfg1 Config _ = Parse(&cfg1) // parse with generics: cfg2, _ := ParseAs[Config]() fmt.Print(cfg1.Foo, cfg2.Foo)
Output: barbar
Index ¶
- func Must[T any](t T, err error) T
- func Parse(v interface{}) error
- func ParseAs[T any]() (T, error)
- func ParseAsWithOptions[T any](opts Options) (T, error)
- func ParseWithOptions(v interface{}, opts Options) error
- func ToMap(env []string) map[string]string
- type AggregateError
- type EmptyEnvVarError
- type EnvVarIsNotSetError
- type FieldParams
- type LoadFileContentError
- type NoParserError
- type NoSupportedTagOptionError
- type NotStructPtrError
- type OnSetFn
- type Options
- type ParseError
- type ParseValueError
- type ParserFunc
Examples ¶
- Package
- Parse
- Parse (ComplexSlices)
- Parse (CustomTimeFormat)
- Parse (ErrorHandling)
- Parse (Expand)
- Parse (FromFile)
- Parse (Init)
- Parse (NotEmpty)
- Parse (Prefix)
- Parse (Required)
- Parse (Separator)
- Parse (SetDefaults)
- Parse (Unset)
- ParseAs
- ParseWithOptions (AllFieldsRequired)
- ParseWithOptions (CustomTypes)
- ParseWithOptions (OnSet)
- ParseWithOptions (Prefix)
- ParseWithOptions (SetEnv)
- ParseWithOptions (TagName)
- ParseWithOptions (UseFieldName)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Parse ¶
func Parse(v interface{}) error
Parse parses a struct containing `env` tags and loads its values from environment variables.
Example ¶
Parse the environment into a struct.
type Config struct { Home string `env:"HOME"` } os.Setenv("HOME", "/tmp/fakehome") var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Home:/tmp/fakehome}
Example (ComplexSlices) ¶
Handling slices of complex types.
type Test struct { Str string `env:"STR"` Num int `env:"NUM"` } type Config struct { Foo []Test `envPrefix:"FOO"` } os.Setenv("FOO_0_STR", "a") os.Setenv("FOO_0_NUM", "1") os.Setenv("FOO_1_STR", "b") os.Setenv("FOO_1_NUM", "2") var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v\n", cfg)
Output: {Foo:[{Str:a Num:1} {Str:b Num:2}]}
Example (CustomTimeFormat) ¶
By default, env supports anything that implements the `TextUnmarshaler` interface, which includes `time.Time`.
The upside is that depending on the format you need, you don't need to change anything.
The downside is that if you do need time in another format, you'll need to create your own type and implement `TextUnmarshaler`.
// type MyTime time.Time // // func (t *MyTime) UnmarshalText(text []byte) error { // tt, err := time.Parse("2006-01-02", string(text)) // *t = MyTime(tt) // return err // } type Config struct { SomeTime MyTime `env:"SOME_TIME"` } os.Setenv("SOME_TIME", "2021-05-06") var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Print(cfg.SomeTime)
Output: {0 63755856000 <nil>}
Example (ErrorHandling) ¶
type Config struct { Username string `env:"EX_ERR_USERNAME" envDefault:"admin"` Password string `env:"EX_ERR_PASSWORD,notEmpty"` } var cfg Config if err := Parse(&cfg); err != nil { if errors.Is(err, EmptyEnvVarError{}) { fmt.Println("oopsie") } aggErr := AggregateError{} if ok := errors.As(err, &aggErr); ok { for _, er := range aggErr.Errors { switch v := er.(type) { // Handle the error types you need: // ParseError // NotStructPtrError // NoParserError // NoSupportedTagOptionError // EnvVarIsNotSetError // EmptyEnvVarError // LoadFileContentError // ParseValueError case EmptyEnvVarError: fmt.Println("daisy") default: fmt.Printf("Unknown error type %v", v) } } } } fmt.Printf("%+v", cfg)
Output: oopsie daisy {Username:admin Password:}
Example (Expand) ¶
If you set the `expand` option, environment variables (either in `${var}` or `$var` format) in the string will be replaced according with the actual value of the variable. For example:
type Config struct { Expand1 string `env:"EXPAND_1,expand"` Expand2 string `env:"EXPAND_2,expand" envDefault:"ABC_${EXPAND_1}"` } os.Setenv("EXPANDING", "HI") os.Setenv("EXPAND_1", "HELLO_${EXPANDING}") var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Expand1:HELLO_HI Expand2:ABC_HELLO_HI}
Example (FromFile) ¶
The `env` tag option `file` (e.g., `env:"tagKey,file"`) can be added in order to indicate that the value of the variable shall be loaded from a file.
The path of that file is given by the environment variable associated with it.
f, _ := os.CreateTemp("", "") _, _ = io.WriteString(f, "super secret") _ = f.Close() type Config struct { Secret string `env:"SECRET,file"` } os.Setenv("SECRET", f.Name()) var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Secret:super secret}
Example (Init) ¶
You can automatically initialize `nil` pointers regardless of if a variable is set for them or not. This behavior can be enabled by using the `init` tag option.
type Inner struct { A string `env:"OLA" envDefault:"HI"` } type Config struct { NilInner *Inner InitInner *Inner `env:",init"` } var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Print(cfg.NilInner, cfg.InitInner)
Output: <nil> &{HI}
Example (NotEmpty) ¶
While `required` demands the environment variable to be set, it doesn't check its value. If you want to make sure the environment is set and not empty, you need to use the `notEmpty` tag option instead (`env:"SOME_ENV,notEmpty"`).
type Config struct { Nope string `env:"NOPE,notEmpty"` } os.Setenv("NOPE", "") var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: env: environment variable "NOPE" should not be empty {Nope:}
Example (Prefix) ¶
Setting prefixes for inner types.
type Inner struct { Foo string `env:"FOO,required"` } type Config struct { A Inner `envPrefix:"A_"` B Inner `envPrefix:"B_"` } os.Setenv("A_FOO", "a") os.Setenv("B_FOO", "b") var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {A:{Foo:a} B:{Foo:b}}
Example (Required) ¶
type Config struct { Nope string `env:"NOPE,required"` } var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: env: required environment variable "NOPE" is not set {Nope:}
Example (Separator) ¶
You can use `envSeparator` to define which character should be used to separate array items in a string. Similarly, you can use `envKeyValSeparator` to define which character should be used to separate a key from a value in a map. The defaults are `,` and `:`, respectively.
type Config struct { Map map[string]string `env:"CUSTOM_MAP" envSeparator:"-" envKeyValSeparator:"|"` } os.Setenv("CUSTOM_MAP", "k1|v1-k2|v2") var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Map:map[k1:v1 k2:v2]}
Example (SetDefaults) ¶
You can define the default value for a field by either using the `envDefault` tag, or when initializing the `struct`.
Default values defined as `struct` tags will overwrite existing values during `Parse`.
type Config struct { Foo string `env:"DEF_FOO"` Bar string `env:"DEF_BAR" envDefault:"bar"` } cfg := Config{ Foo: "foo", } if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Foo:foo Bar:bar}
Example (Unset) ¶
The `env` tag option `unset` (e.g., `env:"tagKey,unset"`) can be added to ensure that some environment variable is unset after reading it.
type Config struct { Secret string `env:"SECRET,unset"` } os.Setenv("SECRET", "1234") var cfg Config if err := Parse(&cfg); err != nil { fmt.Println(err) } fmt.Printf("%+v - %s", cfg, os.Getenv("SECRET"))
Output: {Secret:1234} -
func ParseAs ¶
ParseAs parses the given struct type containing `env` tags and loads its values from environment variables.
Example ¶
Parse the environment into a struct using generics.
type Config struct { Home string `env:"HOME"` } os.Setenv("HOME", "/tmp/fakehome") cfg, err := ParseAs[Config]() if err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Home:/tmp/fakehome}
func ParseAsWithOptions ¶
ParseWithOptions parses the given struct type containing `env` tags and loads its values from environment variables.
func ParseWithOptions ¶
ParseWithOptions parses a struct containing `env` tags and loads its values from environment variables.
Example (AllFieldsRequired) ¶
Make all fields required by default.
type Config struct { Username string `env:"EX_USERNAME" envDefault:"admin"` Password string `env:"EX_PASSWORD"` } var cfg Config if err := ParseWithOptions(&cfg, Options{ RequiredIfNoDef: true, }); err != nil { fmt.Println(err) } fmt.Printf("%+v\n", cfg)
Output: env: required environment variable "EX_PASSWORD" is not set {Username:admin Password:}
Example (CustomTypes) ¶
Parse using extra options.
type Thing struct { desc string } type Config struct { Thing Thing `env:"THING"` } os.Setenv("THING", "my thing") c := Config{} err := ParseWithOptions(&c, Options{ FuncMap: map[reflect.Type]ParserFunc{ reflect.TypeOf(Thing{}): func(v string) (interface{}, error) { return Thing{desc: v}, nil }, }, }) if err != nil { fmt.Println(err) } fmt.Print(c.Thing.desc)
Output: my thing
Example (OnSet) ¶
You might want to listen to value sets and, for example, log something or do some other kind of logic.
type config struct { Home string `env:"HOME,required"` Port int `env:"PORT" envDefault:"3000"` IsProduction bool `env:"PRODUCTION"` NoEnvTag bool Inner struct{} `envPrefix:"INNER_"` } os.Setenv("HOME", "/tmp/fakehome") var cfg config if err := ParseWithOptions(&cfg, Options{ OnSet: func(tag string, value interface{}, isDefault bool) { fmt.Printf("Set %s to %v (default? %v)\n", tag, value, isDefault) }, }); err != nil { fmt.Println("failed:", err) } fmt.Printf("%+v", cfg)
Output: Set HOME to /tmp/fakehome (default? false) Set PORT to 3000 (default? true) Set PRODUCTION to (default? false) {Home:/tmp/fakehome Port:3000 IsProduction:false NoEnvTag:false Inner:{}}
Example (Prefix) ¶
Setting prefixes for the entire config.
type Config struct { Foo string `env:"FOO"` } os.Setenv("MY_APP_FOO", "a") var cfg Config if err := ParseWithOptions(&cfg, Options{ Prefix: "MY_APP_", }); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Foo:a}
Example (SetEnv) ¶
Set a custom environment. By default, `os.Environ()` is used.
type Config struct { Username string `env:"EX_USERNAME" envDefault:"admin"` Password string `env:"EX_PASSWORD"` } var cfg Config if err := ParseWithOptions(&cfg, Options{ Environment: map[string]string{ "EX_USERNAME": "john", "EX_PASSWORD": "cena", }, }); err != nil { fmt.Println(err) } fmt.Printf("%+v\n", cfg)
Output: {Username:john Password:cena}
Example (TagName) ¶
Use a different tag name than `env`.
type Config struct { Home string `json:"HOME"` } os.Setenv("HOME", "hello") var cfg Config if err := ParseWithOptions(&cfg, Options{ TagName: "json", }); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Home:hello}
Example (UseFieldName) ¶
If you don't want to set the `env` tag on every field, you can use the `UseFieldNameByDefault` option.
It will use the field name to define the environment variable name. So, `Foo` becomes `FOO`, `FooBar` becomes `FOO_BAR`, and so on.
type Config struct { Foo string } os.Setenv("FOO", "bar") var cfg Config if err := ParseWithOptions(&cfg, Options{ UseFieldNameByDefault: true, }); err != nil { fmt.Println(err) } fmt.Printf("%+v", cfg)
Output: {Foo:bar}
Types ¶
type AggregateError ¶
type AggregateError struct {
Errors []error
}
An aggregated error wrapper to combine gathered errors. This allows either to display all errors or convert them individually List of the available errors ParseError NotStructPtrError NoParserError NoSupportedTagOptionError EnvVarIsNotSetError EmptyEnvVarError LoadFileContentError ParseValueError
func (AggregateError) Error ¶
func (e AggregateError) Error() string
type EmptyEnvVarError ¶
type EmptyEnvVarError struct {
Key string
}
This error occurs when the variable which must be not empty is existing but has an empty value Read about not empty fields: https://github.com/caarlos0/env#not-empty-fields
func (EmptyEnvVarError) Error ¶
func (e EmptyEnvVarError) Error() string
type EnvVarIsNotSetError ¶
type EnvVarIsNotSetError struct {
Key string
}
This error occurs when the required variable is not set Read about required fields: https://github.com/caarlos0/env#required-fields
func (EnvVarIsNotSetError) Error ¶
func (e EnvVarIsNotSetError) Error() string
type FieldParams ¶
type FieldParams struct { OwnKey string Key string DefaultValue string HasDefaultValue bool Required bool LoadFile bool Unset bool NotEmpty bool Expand bool Init bool }
FieldParams contains information about parsed field tags.
func GetFieldParams ¶
func GetFieldParams(v interface{}) ([]FieldParams, error)
GetFieldParams parses a struct containing `env` tags and returns information about tags it found.
func GetFieldParamsWithOptions ¶
func GetFieldParamsWithOptions(v interface{}, opts Options) ([]FieldParams, error)
GetFieldParamsWithOptions parses a struct containing `env` tags and returns information about tags it found.
type LoadFileContentError ¶
This error occurs when it's impossible to load the value from the file Read about From file feature: https://github.com/caarlos0/env#from-file
func (LoadFileContentError) Error ¶
func (e LoadFileContentError) Error() string
type NoParserError ¶
This error occurs when there is no parser provided for given type Supported types and defaults: https://github.com/caarlos0/env#supported-types-and-defaults How to create a custom parser: https://github.com/caarlos0/env#custom-parser-funcs
func (NoParserError) Error ¶
func (e NoParserError) Error() string
type NoSupportedTagOptionError ¶
type NoSupportedTagOptionError struct {
Tag string
}
This error occurs when the given tag is not supported In-built supported tags: "", "file", "required", "unset", "notEmpty", "expand", "envDefault", "envSeparator" How to create a custom tag: https://github.com/caarlos0/env#changing-default-tag-name
func (NoSupportedTagOptionError) Error ¶
func (e NoSupportedTagOptionError) Error() string
type NotStructPtrError ¶
type NotStructPtrError struct{}
The error occurs when pass something that is not a pointer to a Struct to Parse
func (NotStructPtrError) Error ¶
func (e NotStructPtrError) Error() string
type Options ¶
type Options struct { // Environment keys and values that will be accessible for the service. Environment map[string]string // TagName specifies another tag name to use rather than the default 'env'. TagName string // RequiredIfNoDef automatically sets all fields as required if they do not // declare 'envDefault'. RequiredIfNoDef bool // OnSet allows to run a function when a value is set. OnSet OnSetFn // Prefix define a prefix for every key. Prefix string // UseFieldNameByDefault defines whether or not `env` should use the field // name by default if the `env` key is missing. // Note that the field name will be "converted" to conform with environment // variable names conventions. UseFieldNameByDefault bool // Custom parse functions for different types. FuncMap map[reflect.Type]ParserFunc // contains filtered or unexported fields }
Options for the parser.
type ParseError ¶
The error occurs when it's impossible to convert the value for given type.
func (ParseError) Error ¶
func (e ParseError) Error() string
type ParseValueError ¶
This error occurs when it's impossible to convert value using given parser Supported types and defaults: https://github.com/caarlos0/env#supported-types-and-defaults How to create a custom parser: https://github.com/caarlos0/env#custom-parser-funcs
func (ParseValueError) Error ¶
func (e ParseValueError) Error() string
type ParserFunc ¶
ParserFunc defines the signature of a function that can be used within `Options`' `FuncMap`.