Setting Go Flags from Environment Variables

Recently, I needed to update a Go program to allow configuration via environment variables. The program already supported configuration using Go’s flag package. I wondered if there was a way to populate flag variables from the environment, in addition to from the command line. It turns out you can using flag.VisitAll, os.LookupEnv, and flag.Set.

func SetFlagsFromEnvironment() (err error) {
	flag.VisitAll(func(f *flag.Flag) {
		name := strings.ToUpper(strings.Replace(f.Name, "-", "_", -1))
		if value, ok := os.LookupEnv(name); ok {
			err2 := flag.Set(f.Name, value)
			if err2 != nil {
				err = fmt.Errorf("failed setting flag from environment: %w", err2)
			}
		}
	})

	return
}

The function above iterates over the defined flags using flag.VisitAll and attempts to set their value from the environment using flag.Set. For example, the function above sets -my-flag from the environment variable MY_FLAG (if it exists).

I wanted environment variables to be lower priority and get overwritten by command line arguments. I acheived this by calling SetFlagsFromEnvironment() before flag.Parse().

A complete example of this technique is available on The Go Playground.