Documentation ¶
Overview ¶
Package config provides typesafe, cloud native configuration binding from environment variables or files to structs.
Configuration can be done in as little as two lines:
var c MyConfig config.FromEnv().To(&c)
A field's type determines what https://pkg.go.dev/strconv function is called.
All string conversion rules are as defined in the https://pkg.go.dev/strconv package.
time.Duration follows the same parsing rules as https://pkg.go.dev/time#ParseDuration
*net.URL follows the same parsing rules as https://pkg.go.dev/net/url#URL.Parse NOTE: `*net.URL` fields on the struct **must** be a pointer
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: https://tour.golang.org/basics/12.
Nested structs/subconfigs are delimited with double underscore.
PARENT__CHILD
Env vars map to struct fields case insensitively. NOTE: Also true when using struct tags.
Example ¶
package main import ( "fmt" "os" "github.com/JeremyLoy/config" ) type MySubConfig struct { IPWhitelist []string } type MyConfig struct { DatabaseURL string `config:"DATABASE_URL"` Port int FeatureFlag bool `config:"FEATURE_FLAG"` SubConfig MySubConfig } func main() { os.Clearenv() os.Setenv("DATABASE_URL", "db://") os.Setenv("PORT", "1234") os.Setenv("FEATURE_FLAG", "true") // also accepts t, f, 0, 1 etc. see strconv package. // Double underscore for sub structs. Space separation for slices. os.Setenv("SUBCONFIG__IPWHITELIST", "0.0.0.0 1.1.1.1 2.2.2.2") var c MyConfig config.FromEnv().To(&c) fmt.Println(c.DatabaseURL) fmt.Println(c.Port) fmt.Println(c.FeatureFlag) fmt.Println(c.SubConfig.IPWhitelist, len(c.SubConfig.IPWhitelist)) }
Output: db:// 1234 true [0.0.0.0 1.1.1.1 2.2.2.2] 3
Example (Defaults) ¶
package main import ( "fmt" "os" "github.com/JeremyLoy/config" ) type MySubConfig struct { IPWhitelist []string } type MyConfig struct { DatabaseURL string `config:"DATABASE_URL"` Port int FeatureFlag bool `config:"FEATURE_FLAG"` SubConfig MySubConfig } func main() { os.Clearenv() os.Setenv("DATABASE_URL", "production://") // existing values on the struct are maintained if unset in the env c := MyConfig{ DatabaseURL: "development://", Port: 1234, } config.FromEnv().To(&c) fmt.Println(c.DatabaseURL) fmt.Println(c.Port) }
Output: production:// 1234
Example (ErrorHandling) ¶
package main import ( "fmt" "os" "github.com/JeremyLoy/config" ) type MySubConfig struct { IPWhitelist []string } type MyConfig struct { DatabaseURL string `config:"DATABASE_URL"` Port int FeatureFlag bool `config:"FEATURE_FLAG"` SubConfig MySubConfig } func main() { os.Clearenv() os.Setenv("PORT", "X") var c MyConfig err := config.FromEnv().To(&c) fmt.Println(err) }
Output: config: the following fields had errors: [port]
Example (FromFileWithOverride) ¶
package main import ( "fmt" "os" "strings" "github.com/JeremyLoy/config" ) type MySubConfig struct { IPWhitelist []string } type MyConfig struct { DatabaseURL string `config:"DATABASE_URL"` Port int FeatureFlag bool `config:"FEATURE_FLAG"` SubConfig MySubConfig } func main() { tempFile, _ := os.CreateTemp("", "temp") tempFile.Write([]byte(strings.Join([]string{"PORT=1234", "FEATURE_FLAG=true"}, "\n"))) tempFile.Close() os.Clearenv() os.Setenv("DATABASE_URL", "db://") os.Setenv("PORT", "5678") var c MyConfig config.From(tempFile.Name()).FromEnv().To(&c) // db:// was only set in ENV fmt.Println(c.DatabaseURL) // 1234 was overridden by 5678 fmt.Println(c.Port) // FeatureFlag was was only set in file fmt.Println(c.FeatureFlag) }
Output: db:// 5678 true
Example (StructTags) ¶
package main import ( "fmt" "os" "github.com/JeremyLoy/config" ) func main() { type MyConfig struct { // NOTE: even when using tags, lookup is still case insensitive. // dAtABase_urL would still work. DatabaseURL string `config:"DATABASE_URL"` } os.Clearenv() os.Setenv("DATABASE_URL", "db://") var c MyConfig config.FromEnv().To(&c) fmt.Println(c.DatabaseURL) }
Output: db://
Example (Subconfig) ¶
package main import ( "fmt" "os" "github.com/JeremyLoy/config" ) type MySubConfig struct { IPWhitelist []string } func main() { os.Clearenv() os.Setenv("SUBCONFIG__IPWHITELIST", "0.0.0.0 1.1.1.1 2.2.2.2") var c MySubConfig config.FromEnv().Sub(&c, "SUBCONFIG") fmt.Println(c.IPWhitelist, len(c.IPWhitelist)) }
Output: [0.0.0.0 1.1.1.1 2.2.2.2] 3
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder contains the current configuration state.
func FromEnv ¶
func FromEnv() *Builder
FromEnv returns a new Builder, populated with environment variables
func FromOptional ¶ added in v1.5.0
FromOptional returns a new Builder, populated with the values from file if it exists.
func (*Builder) From ¶
From merges new values from file into the current config state, returning the Builder.
func (*Builder) FromEnv ¶
FromEnv merges new values from the environment into the current config state, returning the Builder.
func (*Builder) FromOptional ¶ added in v1.5.0
FromOptional merges new values from file (if it exists) into the current config state, returning the Builder.
func (*Builder) Sub ¶ added in v1.4.0
Sub behaves the same as To, however it maps configuration to the struct starting at the given prefix.
func (*Builder) To ¶
To accepts a struct pointer, and populates it with the current config state. Supported fields:
- all int, uint, float variants
- bool, struct, string
- time.Duration
- \*url.URL
- slice of any of the above, except for []struct{}
It returns an error if:
- struct contains unsupported fields (pointers, maps, slice of structs, channels, arrays, funcs, interfaces, complex)
- there were errors doing file i/o
It panics if:
- target is not a struct pointer