My theory on why Go's gofmt has wound up being accepted

March 20, 2017

In Three Months of Go (from a Haskeller's perspective) (via), Michael Walker makes the following observation in passing:

I do find it a little strange that gofmt has been completely accepted, whereas Python’s significant whitespace (which is there for exactly the same reason: enforcing readable code) has been much more contentious across the programming community.

As it happens, I have a theory about this: I think it's important that gofmt only has social force. By this I mean that you can write Go code in whatever style and indentation you want, and the Go compiler will accept it (in some styles you'll have to use more semicolons than in others). This is not the case in Python, where the language itself flatly insists that you use whitespace in roughly the correct way. In Go, the only thing 'forcing' you to put your code through gofmt is the social expectations of the Go community. This is a powerful force (especially when people learning Go also learn 'run your code through gofmt'), but it is a soft force as compared to the hard force of Python's language specification, and so I think people are more accepting of it. Many of the grumpy reactions to Python's indentation rules seem to be not because the formatting it imposes is bad but because people reflexively object to being forced to do it.

(This also means that Go looks more conventional as a programming language; it has explicit block delimiters, for example. I think that people often react to languages that look weird and unconventional.)

There is an important practical side effect of this that is worth noting, which is that your pre-gofmt code can be completely sloppy. You can just slap some code into the file with terrible indentation or no indentation at all, and gofmt will fix it all up for you. This is not the case in Python; because whitespace is part of the grammar, your Python code must have good indentation from the start and cannot be fixed later. This makes it easier to write Go code (and to write it in a wide variety of editors that don't necessarily have smart indentation support and so on).

The combination of these two gives the soft force of gofmt a great deal of power over the long term. It's quite convenient to be able to scribble sloppily formatted code down and then have gofmt make it all nice for you, but if you do this you must go along with gofmt's style choices even if you disagree with some of them. You can hold out and stick to your own style, but you're doing things the hard way as well as the socially disapproved way, and in my personal experience sooner or later it's not worth fighting Go's city hall any more. The lazy way wins out and gofmt notches up another quiet victory.

(It probably also matters that a number of editors have convenient gofmt integration. I wouldn't use it as a fixup tool as much as I do if I had to drop the file from my editor, run gofmt by hand, and then reload the now-changed file. And if it was less of a fixup tool, there would be less soft pressure of 'this is just the easiest way to fix up code formatting so it looks nice'; I'd be more likely to format my Go code 'correctly' in my editor to start with.)

Comments on this page:

another observation I've had about the rise of formatting tools (particularly in the Python world) is that, since the advent of Github, when I send patches to the maintainers of my third-party dependencies, they are much more likely to be applied verbatim to the code.

10 years ago, if I sent a diff, the maintainer would perhaps half the time apply the diff but then twiddle with the code a little before committing it to whatever SCM was in use. Although I was usually fairly careful about honoring whatever formatting style was in use, the maintainers tended to accept divergences as line noise and would fix them.

With the Pull Request model, the onus is shifted to the person making the request, but this presents a challenge: how does a project specify formally what their formatting standards are? Obviously, they can run the linter of their choice against the PR, but it would be nice if PR submitters could avoid that hassle.

The beauty of gofmt/pep8 for me is that, if I'm willing to sacrifice my personal style-cow, I can let the tool fix everything, and the chances of having my editor get all the style cases right is much improved. Also, I can tell users of anything I publish "just use gofmt" and the impedance mismatches go away.

I don’t think petulance (to restate your thesis pointedly and concisely) is the reason. I think what you call a practical side-effect is actually the driver.

In just about every other language, scopes are coded with an edge-triggered signal. Python chose a level-triggered coding instead. That was a mistake, plain and simple. It means the programmer must maintain the signal on a line-by-line basis instead of a scope-by-scope basis.

This precludes tooling to maintain the level information – not just big guns of the gofmt variety, but even small things like reindent-this-region editor features. The level information must be hand-maintained, requiring a programmer’s diligence, humility, and patience, i.e. the opposite of every virtue.

The designers of Go chose to make their style choices the lazy and impatient option, requiring only humility. There is no great mystery to their success.

By Aneurin Price at 2017-03-20 17:24:00:

In just about every other language, scopes are coded with an edge-triggered signal. Python chose a level-triggered coding instead. That was a mistake, plain and simple. It means the programmer must maintain the signal on a line-by-line basis instead of a scope-by-scope basis.

I don't think I've ever seen this put so well, thanks.

By Ross McFarlane at 2017-03-26 08:35:33:

I think you're right about the difference between force and coercion, but I think the motivation might be slightly more subtle.

In python, formatting is something that the user can get wrong. It's a barrier to a working program. For new developers learning the language, this is a seemingly arbitrary decision that stands in the way of them getting something working.

gofmt solely exists to help the developer. Badly formatted programs are still valid. Once you have a working program, gofmt can improve it by making it readable.

By tom westberg at 2017-03-30 10:19:05:

While I agree that the social aspects are important, there's one other difference: in python two programmers can use indentation that looks the same, but isn't (tabs vs spaces). If all editors used only spaces for indentation, not an issue. If all shared tab sizes and usd tabs where possible, not an issue. As it is... it's an issue.

The social vs technical aspect is a very good point that I hadn't considered, thanks for that insight.

Written on 20 March 2017.
« Using Firefox's userContent.css for website-specific fixes
Modern Linux kernel memory allocation rules for higher-order page requests »

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

Last modified: Mon Mar 20 01:01:12 2017
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.