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