Skip to content

Instantly share code, notes, and snippets.

@aryszka
Last active October 6, 2019 16:02
Show Gist options
  • Save aryszka/8f16ccd6aa157239c6d488b1a1797dd6 to your computer and use it in GitHub Desktop.
Save aryszka/8f16ccd6aa157239c6d488b1a1797dd6 to your computer and use it in GitHub Desktop.
Combine config with flags
/*
This small POC shows a possible way to combine a config file with command line flags such that the command line
flags override the settings from the config file.
*/
package main
import (
"flag"
"log"
"os"
yaml "gopkg.in/yaml.v1"
)
type config struct {
Foo string `yaml: "foo"`
Bar string `yaml: "bar"`
Baz string `yaml: "baz"`
configFile string
}
var defaults = config{
Foo: "default foo",
Bar: "default bar",
Baz: "default baz",
}
const fakeConfig = `
foo: configured foo
bar: configured bar
`
func main() {
// fake args:
os.Args = []string{"cmd", "-config-file", "config.yaml", "-foo", "foo from flags"}
// copy defaults:
c := defaults
// init and parse flags:
flag.StringVar(&c.Foo, "foo", defaults.Foo, "just foo")
flag.StringVar(&c.Bar, "bar", defaults.Bar, "just bar")
flag.StringVar(&c.Baz, "baz", defaults.Baz, "just baz")
flag.StringVar(&c.configFile, "config-file", "", "optional base configuration from file")
flag.Parse()
// record only those flags that were provided:
// see: https://godoc.org/flag#Visit
// assumption: Value.String() should return a string that can be used to set the same value
providedFlags := make(map[string]string)
flag.Visit(func(f *flag.Flag) {
providedFlags[f.Name] = f.Value.String()
})
// assume yaml file read:
y := []byte(fakeConfig)
if err := yaml.Unmarshal(y, &c); err != nil {
log.Fatalf("failed to parse config file: %v", err)
}
// apply the flags that were provided again:
for name, value := range providedFlags {
f := flag.Lookup(name)
if f == nil {
log.Fatalf("flag lookup failed: %s", name)
}
if err := f.Value.Set(value); err != nil {
log.Fatalln(err)
}
}
// expecting: config{
// Foo: "foo from flags",
// Bar: "configured bar",
// Baz: "default baz",
// configFile: "config.yaml",
// }
log.Println(c)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment