Package mainer defines types relevant to command entrypoint implementation.
It includes the Stdio
struct that abstracts the I/O and working directory of
a command, and the Parser
struct that implements a simple flag parser with
support for struct tags and environment variables-based argument values.
$ go get github.com/mna/mainer
The code documentation is the canonical source for documentation.
A typical main entrypoint looks like this, where the cmd struct could be implemented in a distinct package so the main package is minimal (just the main function at the end) and the command implementation is easily testable:
type cmd struct {
Help bool `flag:"h,help"`
Version bool `flag:"v,version"`
FooBar string `flag:"foo-bar" env:"FOO_BAR"`
}
func (c *cmd) Validate() error {
// the struct may implement a Validate method, and if it does the
// Parser will call it once the flags are stored in the fields.
return nil
}
func (c *cmd) Main(args []string, stdio mainer.Stdio) mainer.ExitCode {
// parse the flags, using env var <CMD>_FOO_BAR for the --foo-bar
// flag if the flag is not set (where <CMD> defaults to the base name
// of the executable, in uppercase and without extension).
p := &mainer.Parser{EnvVars: true}
if err := p.Parse(args, c); err != nil {
fmt.Fprintln(stdio.Stderr, err)
return mainer.InvalidArgs
}
// execute the command...
return mainer.Success
}
func main() {
var c cmd
os.Exit(int(c.Main(os.Args, mainer.CurrentStdio())))
}
- Requires Go 1.19+.
- Use
github.com/caarlos0/env/v6
as environment-variable parsing package instead ofgithub.com/kelseyhightower/envconfig
(envconfig
is a great package butenv/v6
aligns better with the flags behaviour and has a more consistent struct tag usage). SetFlags
now reports set flags using a canonical flag name (the first flag defined on the field). Which of the various flag aliases was used should not matter (if it does, define distinct fields instead).- More data types are supported for flags (not a breaking change per se, but can mean that a
flag
struct tag that would've failed on older versions would now be valid).
The BSD 3-Clause license.