Using a struct (and one optional description map) as single source of truth to add configuration to Go applications.
Note
This is a very simplistic approach to adding simple key:value pair style configuration to your applications. Nothing more, nothing less.
Should be a simple go get command:
go get github.com/smartfactory-kl/appgofigFirst, create your Config and your ConfigDescriptions (optional, only needed for documentation):
type Config struct {
MyOwnSetting int `default:"10" env:"MY_OWN_SETTING"`
MyStringSetting string `default:"hello" env:"MY_STRING_SETTING" req:"true"`
}
var configDescriptions map[string]string = map[string]string{
"MyOwnSetting": "This is just a simple example description so this map is not empty",
"MyStringSetting": "This is just a string setting that is empty but required.",
}Next, instantiate your config and then read the config values by calling ReadConfig():
cfg := &Config{}
if err := appgofig.ReadConfig(cfg); err != nil {
log.Fatal(err)
}
appgofig.LogConfig(cfg, os.Stdout)Caution
Make sure to use a pointer to your struct, not the struct itself.
Now, using your config should be as easy as accessing the struct itself:
log.Println(cfg.MyOwnSetting)The Config struct determines your whole configuration. You can name it whatever you want.
The following tags are usable:
| Tag Name | Content |
|---|---|
env |
Key used for Environment Variables. If this is empty, it defaults to the field name |
default |
String representation of a default value. Otherwise an empty string is used. |
req |
If set to "true", this config setting cannot be empty. Only applies to string values and is ignored on non-string values. |
mask |
If set to "true", this will mask the value of a field when using LogConfig() |
Example entry:
type Config struct {
MyOwnSetting string `env:"ENV_MY_OWN_SETTING" default:"myDefaultValue" req:"true" mask:"true"`
}Important
Due to my own needs, only four types are allowed: string, int, float64 and bool.
The ReadConfig() method has a second parameter for With...() option functions.
The following are available:
WithReadMode(readMode ConfigReadMode)to set a read modeWithYamlFile(filePath string)to set a specific YAML fileWithNewDefaults(newDefaults map[string]string)to set new defaults (e.g. for testing)
Check the example folder on how to use them.
There are four read modes available:
| ReadMode | Description |
|---|---|
appgofig.ReadModeEnvOnly |
Only uses Environment to read values |
appgofig.ReadModeYamlOnly |
Only uses a YAML file |
appgofig.ReadModeEnvThenYaml |
First read env, then apply YAML (overwriting env values if present). This is the default read mode. |
appgofig.ReadModeYamlThenEnv |
First read YAML, then apply env (overwriting YAML values if present) |
When no YAML file is specified using WithYamlFile(), but a YAML ReadMode is used, this list
of paths is used to look for YAML files. First hit is used:
defaultYamlPaths := []string{"config.yml", "config.yaml", "config/config.yml", "config/config.yaml"}Important
To keep it simple, only flat key:value pair YAMLs are allowed. No nesting should be there.
Two methods are provided to automatically create documentation about your configuration.
Check the example folder for how they could look like.
Using WriteToMarkdownFile() you can generate a markdown file containing a simple table.
if err := appgofig.WriteToMarkdownFile(cfg, configDescriptions, "example/MarkdownExample.md"); err != nil {
log.Fatal(err)
}Similarly, using WriteToYamlExampleFile() will get you a config.yml example with comments explaining each entry
if err := appgofig.WriteToYamlExampleFile(cfg, configDescriptions, "example/ConfigYamlExample.yaml"); err != nil {
log.Fatal(err)
}A basic set of tests is included. To run:
go test -cover ./... -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.htmlYou can admire the coverage in a browser then.