Go's getopt problem

November 11, 2013

The Go standard library is full of good stuff, people will commonly tell you (or tell the world when they write about Go). And then they will add a little qualifier: except for the flag package; you don't want to use that and you should get a sane getopt package. Sometimes the people writing this will name one or two such packages, which usually still leaves you with a problem.

(I saw such a Go-related slide recently that recommended something like 'getopt' or 'go-flags'. Do you know how many people have had the clever idea to write a Go command line argument parser that they call 'getopt'? The answer is 'more than one'. The Go wiki alone lists two, one of which links to four more. I have no idea which specific 'getopt' package the author of the slides thought was the one to use.)

The flags package is perhaps the most frustrating thing about Go for me. Uniquely out of the standard library it is clearly insufficient to fill a common need at even a basic level, yet faced with this common need the Go authors not so much punt as ignore you. If you want standard Unix command line parsing in your Go project (even a very small and otherwise self-contained one), your very first job is to try to sort through a great many options to pick a decent one. In the process you will add an external dependency and as we all know external dependencies are a great way to blow up your little project. All it takes is picking a getopt package that the author decides either not to support any more or to change the API on and whoops, fun times.

(Having your first external dependency also vastly complicates the build instructions for a little Go program. If you have a self-contained little program you can tell your coworkers to run 'go build <foo>.go' or 'gccgo -o <foo> <foo>.go'. Add even one external dependency and suddenly they need $GOPATH and everything that that implies.)

This is asinine. When the common advice is 'replace this standard library package', your standard library is flawed and you should fix this. The Go developers should pick or write one getopt package and put it in the standard library (and keep the flag package for backwards compatibility and for anyone who really needs it).

I don't expect this to happen, of course. If it was going to happen it would have happened already; it's not like this is a new problem.

(After all there's been enough time and demand for all sorts of people to write all sorts of argument parsing packages. Which is part of the problem.)

PS: yes, this is a grumpy rant. I do them sometimes.

(It is a close variant of why I want things to be in the Python standard library, especially for small projects.)


Comments on this page:

By Perry Lorier at 2013-11-12 05:05:05:

What about go's internal flags module don't you like? (I've not coded in go before, so I'm not sure what's going on here). This looks like it's based on Google's flag parsing module (eg http://code.google.com/p/python-gflags/ and http://code.google.com/p/gflags/) which is fairly flexible, and generally has different goals to the normal getopt package (eg independent modules can declare their own flags, and they'll all get bundled into your command line parsing).

Is google's flags not flexible enough? Too flexible?

(Disclaimer: I work for Google, and have used a bajillion programs that take flags in Google flags styles).

By cks at 2013-11-12 10:48:47:

The flag package doesn't give you getopt aka Unix style compatible argument handling. The most glaring issue is that you can't combine multiple flags in one argument; if -t and -v are both boolean flags, you cannot write 'cmd -tv'. There is various fallout from this, including accepting long flags as '-longname' instead of just '--longname'. I don't believe you can easily have flags with both a short and a long form either (eg either '-f file' or '--filename file').

All of this creates Go commands that do not behave like other Unix commands as far as argument handling goes. This is bad; people are used to Unix style command handling and expect it from all Unix commands regardless of what language they're written in. Google is big enough to create its own internal conventions and enforce them, but other people are not.

By Perry Lorier at 2013-11-13 19:52:01:

Hrm, interesting. I must have never have tried combining single character flags.

The python module (the version I'm most familiar with), supports:

 gflags.DEFINE_bool("frobnicator",
                    True,
                    "Enable the frobnicator",
                    short_name="-f")

The go version doesn't seem to support the "--nofrobnicator" syntax which python does. The Python version doesn't do the evil "-frobnicator" hack, but it doesn't parse "-fq" correctly either.

Hmm. Learn something new every day :)

Written on 11 November 2013.
« Are those chassis fans actually still spinning?
The cost of expensive hardware and the benefit of hindsight »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Mon Nov 11 23:43:53 2013
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.