Hacker News new | ask | show | jobs
by tommiegannert 869 days ago
> Enhanced routing patterns

> This change breaks backwards compatibility in small ways, some obvious—patterns with "{" and "}" behave differently— and some less so—treatment of escaped paths has been improved. The change is controlled by a GODEBUG field named httpmuxgo121. Set httpmuxgo121=1 to restore the old behavior.

That's a great enhancement now that the future of Gorilla Mux is shaky. But why doesn't that go against the Go 1 compatibility promise?

> It is intended that programs written to the Go 1 specification will continue to compile and run correctly, unchanged, over the lifetime of that specification.

4 comments

The way they are using to route around the Go 1 compatibility promise is to gate these backwards incompatible changes on the value of the go directive in go.mod. If it says 1.22 or later you get the new library behavior, otherwise you get the old one. We'll see how well this ends up working in practice.
This mimics Perl's "use 5.x", although the latter is scoped per module. Perl's backward compatibility track record validates the soundness of this approach.

Perl can also selectively enable features, in a way not dissimilar to Python's "from _future_ import X", except the latter is about forward compatibility with a future default, whereas Perl is all about backwards compatibility as a sane default.

I guess Go does it at the mod consistent level because it needs a global view of features whereas Perl can dynamically alter itself (including its parser) live.

Usually the Go team scrapes from GitHub and open source programs how people use something before breaking them; I suspect they found little usage of { and } in HTTP handler paths. They also provide a way of opting out the new behaviour, so they don't force you to change anything in your code (but yes, it does require you to set a new env var).

The change to the for loop semantic is another example in this release; it effectively is a breaking change.

All Go programs continue to compile and run, though with minor behavioural changes. I think Go took a pragmatic approach, and that was one of the reasons for its success.

I don't see the point of using semver (or at least telling us about the same guarantees) and then not making use of it.

If there were 10 breaking chances we should be at 11.x now, not at 1.x with 20 environment variables.

From a purist perspective, you're right - the contract has been broken, and a major version should've been incremented.

However, Go has always been more of a pragmatic than a purist language. For example, they've analyzed tons of code and found that most of them had bugs caused by having `for` loop with a single variable being mutated. So they changed the `for` loop (in a technically backwards incompatible way) in order to make all those bugs disappear. In a way, they modified the formal contract to make it more aligned with the de-facto contract that users were expecting.

I personally think that kind of pragmatism beats purism any day. Maybe the fact that I've never personally been affected by Go backwards incompatibilities also plays a role... But I've yet to find a single person who has :)

This has nothing to do with pragmatism. Just update the version number. This is the pragmatic way.
I agree this is a (rare) mistake with Go. If they're going to break versioning using go.mod, they should at least break it in a way that makes it better. I'd much rather have my code fail to compile when we change go.mod to 1.22 than have to detect subtle runtime issues like this.
Because then they would lose their pithy advertising slogan. Minor or not, it is a non-compatible change.