Documentation
¶
Overview ¶
Package cnfg provide basic procedures to parse a config file into a struct, and more powerfully, parse a slew of environment variables into the same or a different struct. These two procedures can be used one after the other in either order (the latter overrides parts of the former).
If this package interests you, pull requests and feature requests are welcomed!
I consider this package the pinacle example of how to configure small Go applications from a file. You can put your configuration into any file format: XML, YAML, JSON, TOML, and you can override any struct member using an environment variable. As it is now, the (env) code lacks map{} support but pretty much any other base type and nested member is supported. Adding more/the rest will happen in time. I created this package because I got tired of writing custom env parser code for every app I make. This simplifies all the heavy lifting and I don't even have to think about it now.
Index ¶
Examples ¶
Constants ¶
const ENVTag = "xml"
ENVTag is the tag to look for on struct members. You may choose to use a custom tag by creating an &ENV{} struct with a different Tag. "env" is popular, but I chose "xml" because the nouns are generally singular, and those look good as env variables. "xml" is also convenient because it's brief and doesn't add yet another struct tag. Those lines can get long quickly.
Variables ¶
This section is empty.
Functions ¶
func UnmarshalENV ¶ added in v0.0.3
UnmarshalENV copies environment variables into configuration values. This is useful for Docker users that find it easier to pass ENV variables than a specific configuration file. Uses reflection to find struct tags.
func UnmarshalFile ¶ added in v0.0.3
UnmarshalFile parses a configuration file (of any format) into a config struct. This is a shorthand method for calling Unmarshal against the json, xml, yaml or toml packages. If the file name contains an appropriate suffix it is unmarshaled with the corresponding package. If the suffix is missing, TOML is assumed. Works with multiple files, so you can have stacked configurations.
func UnmarshalMap ¶ added in v0.0.3
UnmarshalMap parses and processes a map of key/value pairs as though they were environment variables. Useful for testing, or unmarshaling values from places other than environment variables. This version of UnmarshalMap assumes default tag ("xml") and no prefix: ""
Types ¶
type Duration ¶
Duration is useful if you need to load a time Duration from a config file into your application. Use the config.Duration type to support automatic unmarshal from all sources. If you do not use a config file, do not use this type because the environment unmarshaler supports time.Duration natively.
func (*Duration) UnmarshalText ¶
UnmarshalText parses a duration type from a config file. This method works with the Duration type to allow unmarshaling of durations from files and env variables in the same struct. You won't generally call this directly.
type ENV ¶ added in v0.0.3
ENV allows you to parse environment variables using an object instead of global state. This package allows using the default ENVTag from global state, or you can pass in your own using this struct. See the UnmarshalENV function (it's 1 line) for an example of how to use this.
func (*ENV) Unmarshal ¶ added in v0.0.3
Unmarshal parses and processes environment variables into the provided interface. Uses the Prefix and Tag name from the &ENV{} struct values.
Example (Simple) ¶
Complete working example for UnmarshalENV()
// Systems is used to show an example of how to access nested slices. type System struct { Name string `env:"name"` Signal *[]int `env:"signal"` } // Config represents your application's environment variable based config inputs. // Works with or without pointers. type Config struct { Debug bool `env:"debug"` Users []string `env:"user"` Interval *time.Duration `env:"interval"` Systems []*System `env:"system"` } // Make a pointer to your struct with some default data. // Maybe this data came from a config file? Using ParseFile()! c := &Config{ Debug: true, Users: []string{"me", "you", "them"}, } // Okay set some ENV variables. Pretend you did this in bash. os.Setenv("APP_DEBUG", "false") // turn off debug os.Setenv("APP_USER_1", "dad") // replace "you" with "dad" os.Setenv("APP_USER_3", "mom") // add "mom" os.Setenv("APP_INTERVAL", "7m1s") // don't forget the interval!! // This adds (creates) systems and signals in sub-slices. os.Setenv("APP_SYSTEM_0_NAME", "SysWon") os.Setenv("APP_SYSTEM_1_NAME", "SysToo") os.Setenv("APP_SYSTEM_1_SIGNAL_0", "12") // You can add as many as you like, as long as they are in numerical order. os.Setenv("APP_SYSTEM_1_SIGNAL_1", "77") fmt.Printf("BEFORE => Debug: %v, Interval: %v, Users: %v, Systems: %v\n", c.Debug, c.Interval, c.Users, c.Systems) // Make a ENV Decoder with special tag and prefix. env := &ENV{Tag: "env", Pfx: "APP"} // Run Unmarshal to parse the values into your config pointer: ok, err := env.Unmarshal(c) if err != nil { panic(err) } // And optionally, do something with the "ok" return value. // If you wanted to overwrite ALL configs if ANY env variables are present // you could use ok to make and if statement that does that. if ok { fmt.Println("~ Environment variables were parsed into the config!") } // If you don't set an env variable for it, it will stay nil. // Same for structs and slices. if c.Interval == nil { fmt.Printf("You forgot to set an interval!") return } fmt.Printf("AFTER => Debug: %v, Interval: %v, Users: %v\n", c.Debug, *c.Interval, c.Users) // We added some systems, check them! for i, s := range c.Systems { fmt.Printf(" %v: System Name: %v, Signals: %v\n", i, s.Name, s.Signal) }
Output: BEFORE => Debug: true, Interval: <nil>, Users: [me you them], Systems: [] ~ Environment variables were parsed into the config! AFTER => Debug: false, Interval: 7m1s, Users: [me dad them mom] 0: System Name: SysWon, Signals: <nil> 1: System Name: SysToo, Signals: &[12 77]
func (*ENV) UnmarshalMap ¶ added in v0.0.3
UnmarshalMap parses and processes a map of key/value pairs as though they were environment variables. Useful for testing, or unmarshaling values from places other than environment variables. Use this version of UnmarshalMap if you need to change the tag or prefix.
type ENVUnmarshaler ¶
ENVUnmarshaler allows custom unmarshaling on a custom type. If your type implements this, it will be called and the logic stops there.
Example ¶
This simple example shows how you may use the ENVUnmarshaler interface. This shows how to use two environment variables to set one custom value.
package main import ( "fmt" "os" "strconv" "time" ) // TimeX uses two environment variables to multiply a duration. type TimeX struct { time.Duration } // This is a test to make sure our struct satisfies the interface. var _ ENVUnmarshaler = (*TimeX)(nil) type AppConfig struct { Name string `xml:"name"` Special TimeX `xml:"in"` } func (t *TimeX) UnmarshalENV(tag, val string) error { xTag := tag + "_X" xString, ok := os.LookupEnv(xTag) if !ok { xString = "1" } multiplier, err := strconv.Atoi(xString) if err != nil { return fmt.Errorf("multiplier invalid %s: %v", xTag, err) } t.Duration, err = time.ParseDuration(val) if err != nil { return fmt.Errorf("duration invalid %s: %v", tag, err) } t.Duration *= time.Duration(multiplier) return nil } // This simple example shows how you may use the ENVUnmarshaler interface. // This shows how to use two environment variables to set one custom value. func main() { c := &AppConfig{} os.Setenv("APP_IN", "5m") os.Setenv("APP_IN_X", "10") os.Setenv("APP_NAME", "myApp") _, err := UnmarshalENV(c, "APP") if err != nil { panic(err) } fmt.Printf("%s starts in %v", c.Name, c.Special) }
Output: myApp starts in 50m0s
type Pairs ¶ added in v0.0.3
Pairs represents pairs of environment variables.
func MapEnvPairs ¶ added in v0.0.3
MapEnvPairs turns the pairs returned by os.Environ() into a map[string]string. Providing a prefix returns only variables with that prefix.