I'm working on a project written in Go, and I've gotten to the point where I need to pick a command-line parsing library. I'm not fond of the standard flag package for a couple of reasons:
- its syntax does not follow GNU conventions
- its default help output is ugly
So I thought I'd shop around and see what's out there. What follows are my impressions of all the command-line parsing libraries listed in the Go Project Dashboard.
Disclaimer: I'm the original author of the Python standard library module optparse, so I'm biased in favour of convenient, automated conversion of command-line options to programmer-accessible variables. I also like automatic generation of nice-looking help. And I prefer GNU style:
- single dash for short options (-v)
- multiple short options can be coalesced (-ab is equivalent to -a -b)
- double dash for long options (--verbose)
- options terminated by lone --
- options can be interspersed with positional args
Executive summary: I evaluated 8 of the libraries listed in the Go Project Dashboard. Three of them look promising:
- launchpad.net/gnuflag
- github.com/gaal/go-options
- github.com/ogier/pflag
The remainder appear to be incomplete and/or abandoned (eg. they don't build, are undocumented, or have no unit tests).
All evaluations were done with Go 1.0.3 using the latest version of each package as of December 18, 2012.
Claims to be a compatible with the standard flag package, but supports GNU/POSIX syntax instead.
Pros:
- mostly works as advertised: implements some of GNU/POSIX syntax
- documented
- tested
- compiles and works
Cons:
- does not conform to current "go build" rules (but the fix is trivial)
- no support for aliases: -q and --quiet are entirely different options, and will get separate entries in help output
- does not support option clustering (-ab equivalent to -a -b)
- similarly, does not treat -abfoo as equivalent to -a -b foo
- does not allow abbreviation of long options
- default help output is ugly (but gnuflag provides an easy hook to override its help output)
Undocumented, so I did not evaluate it.
Like gnuflag, claims to be compatible with flag but support GNU/POSIX syntax. I could not verify this for myself, since it does not build.
Pros:
- documented
- comes with an example program
Cons:
- does not build with "go build" or with the supplied Makefile (appears to predate "go build")
- no unit tests (there is a test program, but it doesn't build either)
Yet another implementation of GNU/POSIX syntax, but using a totally different API from flag. You write a big string that describes all of your options, and the library parses it at runtime and then parses the command line. Panics if your specification is malformed.
Pros:
- mostly works as advertised: implements some of GNU/POSIX syntax
- nicely documented
- tested
- easy-to-use API
- generates decent-looking help
- compiles and works (modulo limitations below)
Cons:
- does not support option clustering (-ab equivalent to -a -b)
- similarly, does not treat -abfoo as equivalent to -a -b foo
- sloppy syntax: treats -verbose equivalent to --verbose
- some people might dislike the dynamic API and prefer compile-time checking (doesn't bother me)
Similar idea to go-options, but the documentation is very thin. As a result, I was unable to get it to work.
Cons:
- insufficient documentation
- does not work (at least not for me)
- generated help is not very helpful
Appears to be based on my Python module optparse, so I have an inherent bias in favour of this one. Unfortunately, it doesn't build.
Pros:
- should implement all of GNU/POSIX syntax, since optparse does
- should support option aliases, since optparse does
- should support abbreviation of long options, since optparse does
(the above are presumptions, not verified by reading the code or trying it)
Cons:
- not compatible with "go build" (mixed packages in same directory)
- uses lots of obsolete library packages (needs "go fix")
- even then, it still doesn't compile
- no documentation
Pros:
- some documentation
Cons:
- documentation doesn't give high-level overview; you just have to figure it out
- no unit tests (there are two *_test.go files, but they test almost nothing)
- does not treat --file foo equivalent to --file=foo
- doesn't support abbreviation of long options
- help generation code is incomplete -- doesn't actually generate help
Yet another implementation of GNU/POSIX syntax using the same API as flag.
Pros:
- documented
- unit tests
- supports long and short options
- supports option clustering
- treats -abfoo equivalent to -a -bfoo
Cons:
- not compatible with "go build" / "go test" (but the fix is trivial)
- no support for abbreviating long options
- does not treat --file foo equivalent to --file=foo