-
-
Save xeoncross/707ee4a6a7fff8b73baa74a1071c382e to your computer and use it in GitHub Desktop.
Flags, environment variables, and .env file config loading https://play.golang.org/p/pautLXl7yMW
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MYSQL_HOST=127.0.0.1 | |
MYSQL_USER=hello | |
MYSQL_PASS=world | |
MYSQL_NAME=myapp | |
MYSQL_PORT=3306 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"flag" | |
"fmt" | |
"io" | |
"os" | |
"strings" | |
"github.com/peterbourgon/ff" | |
) | |
func main() { | |
_, err := New() | |
if err != nil { | |
fmt.Println(err) | |
} | |
} | |
// Config for the root command, including flags and types that should be | |
// available to each subcommand. | |
type Config struct { | |
MySQL mysqlConfig | |
Verbose bool | |
} | |
type mysqlConfig struct { | |
User string | |
Pass string | |
Host string | |
Port string | |
Name string | |
} | |
func New() (*Config, error) { | |
c := &Config{} | |
fs := flag.NewFlagSet("app", flag.ExitOnError) | |
fs.StringVar(&c.MySQL.Host, "MYSQL_HOST", "", "MySQL host") | |
fs.StringVar(&c.MySQL.Port, "MYSQL_POST", "", "MySQL port") | |
fs.StringVar(&c.MySQL.User, "MYSQL_USER", "", "MySQL username") | |
fs.StringVar(&c.MySQL.Pass, "MYSQL_PASS", "", "MySQL password") | |
fs.StringVar(&c.MySQL.Name, "MYSQL_NAME", "", "MySQL database name") | |
fs.BoolVar(&c.Verbose, "v", false, "log verbose output") | |
return c, ff.Parse(fs, | |
os.Args[1:], | |
ff.WithEnvVarNoPrefix(), | |
ff.WithConfigFileParser(EnvParser), | |
// ff.WithConfigFileParser(ff.JSONParser), | |
// ff.WithConfigFileParser(ff.PlainParser), | |
ff.WithConfigFileFlag("config-file"), | |
) | |
} | |
// EnvParser is a parser for config files in an extremely simple format. Each | |
// line is tokenized as a single key/value pair. The first whitespace-delimited | |
// token in the line is interpreted as the flag name, and all remaining tokens | |
// are interpreted as the value. Any leading hyphens on the flag name are | |
// ignored. | |
func EnvParser(r io.Reader, set func(name, value string) error) error { | |
s := bufio.NewScanner(r) | |
for s.Scan() { | |
line := strings.TrimSpace(s.Text()) | |
if line == "" { | |
continue // skip empties | |
} | |
if line[0] == '#' { | |
continue // skip comments | |
} | |
var ( | |
name string | |
value string | |
index = strings.IndexRune(line, '=') | |
) | |
if index < 0 { | |
name, value = line, "true" // boolean option | |
} else { | |
name, value = line[:index], strings.TrimSpace(line[index+1:]) | |
} | |
fmt.Println("env:", name, value, index) | |
// remove ending comment | |
if i := strings.Index(value, " #"); i >= 0 { | |
value = strings.TrimSpace(value[:i]) | |
} | |
if err := set(name, value); err != nil { | |
return err | |
} | |
} | |
return nil | |
} | |
// or you can just wrap what already exists | |
func EnvTransformParser(r io.Reader, set func(name, value string) error) error { | |
b, err := ioutil.ReadAll(r) | |
if err != nil { | |
return err | |
} | |
r = bytes.NewReader(bytes.ReplaceAll(b, []byte("="), []byte(" "))) | |
return ff.PlainParser(r, set) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment