Cfgenv loads config structs from environment vars.
Struct field types supported:
- native type -
string
,bool
,int
,int8
,int16
,int32
,int64
,uint
,uint8
,uint16
,uint32
,uint64
,float32
,float64
,time.Duration
- pointer native type -
*string
,*bool
,*int
,*int8
,*int16
,*int32
,*int64
,*uint
,*uint8
,*uint16
,*uint32
,*uint64
,*float32
,*float64
,*time.Duration
- environment var is optional and value is not set if the env var is missing []V
(slice) whereV
is native type or pointer native typemap[K]V
whereK
is native type andV
is native type or pointer native type- embedded structs & struct fields
- other types can be handled by providing a
cfgenv.CustomerSetterOption
- load config from environment variables or from file (e.g.
.env
file) or any otherio.Reader
Example:
package main
import (
"fmt"
"github.com/go-andiamo/cfgenv"
)
type DbConfig struct {
Host string `env:"optional,default=localhost"`
Port uint `env:"optional,default=3601"`
Username string
Password string
}
type Config struct {
ServiceName string
Database DbConfig `env:"prefix=DB"`
}
func main() {
cfg := &Config{}
err := cfgenv.Load(cfg)
if err != nil {
panic(err)
} else {
fmt.Printf("%+v\n", cfg)
}
}
would effectively load from environment...
SERVICE_NAME=foo
DB_HOST=localhost
DB_PORT=33601
DB_USERNAME=root
DB_PASSWORD=root
To install cfgenv, use go get:
go get github.com/go-andiamo/cfgenv
To update cfgenv to the latest version, run:
go get -u github.com/go-andiamo/cfgenv
Fields in config structs can use the env
tag to override cfgenv loading behaviour
Tag | Purpose |
---|---|
env:"MY" env:"name=MY env:"name='MY'" |
overrides the environment var name to read with MY |
env:"optional" |
denotes the environment var is optional |
env:"default=foo" |
denotes the default value if the environment var is missing |
env:"prefix=SUB" |
(on a struct field) denotes all fields in the struct will load from env var names prefixed with SUB_ |
env:"prefix=SUB_" |
(on a map[string]string field) denotes the map will read all env vars whose name starts with SUB_ |
env:"match='\d{3}'" |
(on a map[string]string field) denotes the map will read all env vars whose name matches the regexp \d{3} |
env:"delimiter=;" env:"delim=;" |
(on slice and map fields) denotes the character used to delimit items(the default is , ) |
env:"separator=:" env:"sep=:" |
(on map fields) denotes the character used to separate key and value(the default is : ) |
env:"encodng=base64" |
denotes the environment var is encoded as base64 and will be decoded.Built-in decoders are base64 , base64url , rawBase64 (no padding) & rawBase64url (no padding)Other decoders are supported by passing a Decoder interface as an option to Load() /LoadAs() |
env:"expand" |
denotes the environment var is always expanded (even if no Expand() is passed to Load() /LoadAs() ) |
env:"no-expand" |
denotes the environment var is never expanded (even if an Expand() is passed to Load() /LoadAs() ) |
When loading config from environment vars, several option interfaces can be passed to cfgenv.Load()
function to alter the names of expected environment vars
or provide support for extra field types.
cfgenv.PrefixOption
Alters the prefix for all environment vars
(Implement interface or use cfgenv.NewPrefix(prefix string)
Example:
package main
import (
"fmt"
"github.com/go-andiamo/cfgenv"
)
type Config struct {
ServiceName string
}
func main() {
cfg := &Config{}
err := cfgenv.Load(cfg, cfgenv.NewPrefix("MYAPP"))
if err != nil {
panic(err)
} else {
fmt.Printf("%+v\n", cfg)
}
}
to load from environment variables...
MYAPP_SERVICE_NAME=foo
cfgenv.SeparatorOption
Alters the separators used between prefixes and field names for environment vars
(Implement interface or use cfgenv.NewSeparator(separator string)
Example:
package main
import (
"fmt"
"github.com/go-andiamo/cfgenv"
)
type DbConfig struct {
Host string `env:"optional,default=localhost"`
Port uint `env:"optional,default=3601"`
Username string
Password string
}
type Config struct {
ServiceName string
Database DbConfig `env:"prefix=DB"`
}
func main() {
cfg := &Config{}
err := cfgenv.Load(cfg, cfgenv.NewPrefix("MYAPP"), cfgenv.NewSeparator("."))
if err != nil {
panic(err)
} else {
fmt.Printf("%+v\n", cfg)
}
}
to load from environment variables...
MYAPP.SERVICE_NAME=foo
MYAPP.DB.HOST=localhost
MYAPP.DB.PORT=33601
MYAPP.DB.USERNAME=root
MYAPP.DB.PASSWORD=root
cfgenv.NamingOption
Overrides how environment variable names are deduced from field names
Example:
package main
import (
"fmt"
"github.com/go-andiamo/cfgenv"
"reflect"
"strings"
)
type DbConfig struct {
Host string `env:"optional,default=localhost"`
Port uint `env:"optional,default=3601"`
Username string
Password string
}
type Config struct {
ServiceName string
Database DbConfig `env:"prefix=DB"`
}
func main() {
cfg := &Config{}
err := cfgenv.Load(cfg, &LowercaseFieldNames{}, cfgenv.NewSeparator("."))
if err != nil {
panic(err)
} else {
fmt.Printf("%+v\n", cfg)
}
}
type LowercaseFieldNames struct{}
func (l *LowercaseFieldNames) BuildName(prefix string, separator string, fld reflect.StructField, overrideName string) string {
name := overrideName
if name == "" {
name = strings.ToLower(fld.Name)
}
if prefix != "" {
name = prefix + separator + name
}
return name
}
to load from environment variables...
servicename=foo
DB.host=localhost
DB.port=33601
DB.username=root
DB.password=root
cfgenv.ExpandOption
Providing an cfgenv.ExpandOption
to the cfgenv.Load()
function allows support for resolving substitute environment variables - e.g. EXAMPLE=${FOO}-{$BAR}
Use the Expand()
function - or implement your own ExpandOption
Example - see expand_option
cfgenv.CustomSetterOption
Provides support for custom struct field types
Example - see custom_setter_option
cfgenv.EnvReader
Reads environment vars from specified reader (e.g. cfgenv.NewEnvFileReader()
)
Example:
package main
import (
"fmt"
"github.com/go-andiamo/cfgenv"
"os"
)
type Config struct {
ServiceName string
}
func main() {
cfg := &Config{}
f, err := os.Open("local.env")
if err != nil {
panic(err)
}
defer f.Close()
err = cfgenv.Load(cfg, cfgenv.NewEnvFileReader(f, nil))
if err != nil {
panic(err)
} else {
fmt.Printf("%+v\n", cfg)
}
}
where file local.env
looks like...
# this is the service name...
SERVICE_NAME=foo
Cfgenv can also write examples and current config using the cfgenv.Example()
or cfgenv.Write()
functions.
Example - see write_example