As I commented[1] I think the syntax is flawed in the proposal. You need to weirdly create a magic string to define your handler. Why not make it an actual argument, then using already existing constants is easier. [1] https://github.com/golang/go/issues/61410#issuecomment-16580...
Better HTTP server routing in Go 1.22
11–20 of 236 posts
Re: Better HTTP server routing in Go 1.22
#12Forcing a panic when 2 routes are matched seems counter intuitive to me (versus, idk, every other web framework which uses the first-to-be-registered route that matches). Are there go-specific reasons for that? The edge case of "you might register HTTP routes in a bunch of places and it's harder to find that if multiple routes match" seems like something that be worked around with tooling. I've (ab)used the behavior…
From the design proposal[1]:
> Using specificity for matching is easy to describe and
> preserves the order-independence of the original ServeMux
> patterns. But it can be hard to see at a glance which of
> two patterns is the more specific, or why two patterns
> conflict. For that reason, the panic messages that are
> generated when conflicting patterns are registered will
> demonstrate the conflict by providing example paths, as in
> the previous paragraph.
See also the background discussion[2]: > The semantics of the mux do not depend on the order of the
> Handle or HandleFunc calls. Being order-independent makes
> it not matter what order packages are initialized (for
> init-time registrations) and allows easier refactoring of
> code. This is why the tie breakers are not based on
> registration order and why duplicate registrations panic
> (only order could possibly distinguish them). It remains a
> key design goal to avoid any semantics that depend on
> registration order.
[1]: https://github.com/golang/go/issues/61410
[2]: https://github.com/golang/go/discussions/60227Re: Better HTTP server routing in Go 1.22
#13Forcing a panic when 2 routes are matched seems counter intuitive to me (versus, idk, every other web framework which uses the first-to-be-registered route that matches). Are there go-specific reasons for that? The edge case of "you might register HTTP routes in a bunch of places and it's harder to find that if multiple routes match" seems like something that be worked around with tooling. I've (ab)used the behavior…
In general, the reason you use a compiled / typed language like golang at all (instead of, say, perl) is to "left shift" your bugs: A bug caught when you first spin up your application is better than a bug caught after a corner case acts up in the wild, and a bug caught when you compile is better than a bug caught when you first spin up your application.
I recently ran a cross a bug in a side project of mine (using gorilla/mux) where I had accidentally made overlapping routes. If the router had panic'ed instead of running, I would have been nudged to refactor the URLs and completely avoided the bug.
Re: Better HTTP server routing in Go 1.22
#14Will this finally end the eternal golang http router bikeshedding?
Re: Better HTTP server routing in Go 1.22
#15Forcing a panic when 2 routes are matched seems counter intuitive to me (versus, idk, every other web framework which uses the first-to-be-registered route that matches). Are there go-specific reasons for that? The edge case of "you might register HTTP routes in a bunch of places and it's harder to find that if multiple routes match" seems like something that be worked around with tooling. I've (ab)used the behavior…
The panic is the tooling. It ensures that you can’t write code that becomes ambiguous and hard to reason about, or become dependent on something random like the order code is initialised in, which may change for completely arbitrary reasons (for example renaming a file your taking advantage of Go’s special file level init func).
> I've (ab)used the behavior of "first to be matched wins" a ton in my career - there's been a bunch of "business case" times when I've needed like `/foo/bar` to be one registered route, and `/foo/{id}` to be another.
It’s pretty trivial to write a handler that accepts the base path, and then routes to a different set of handler functions. Then the routing is clear and explicit.
Ultimately if you want the behaviour not in the stdlib, plenty of other libraries exist out there with more functionality.
The Go stdlib, and language in general has always skewed towards conservative behaviour in the face of possible ambiguity. Something I’ve always appreciated, because it means it’s easy build a strong and accurate intuition of how the stdlib works. You rarely find yourself in situations where what you think is the “obvious” answer isn’t the correct answer, simply because your idea of “obvious” doesn’t perfectly align with the authors idea of “obvious”. Being able to quickly and accurately read and understand code is far more valuable than saving a handful of seconds when writing it.
Re: Better HTTP server routing in Go 1.22
#16Re: Better HTTP server routing in Go 1.22
#17I would far rather the overlapping path’s just match in the order they were defined rather than panic. In their example here, had they defined the `/task/0/{action}/` path before the wildcard path, my expectation would have been for that to match first. This would allow for handlers for special cases to easily be defined. I’d far rather things just do what I say than fail in “helpful” ways. Smells really funny and no…
The original ServeMux was designed to not honor registration order, because it is risky to do so. One of the key design goals of Go is to support "programming at scale", and odd side-effects due to edits made to "distant code" is the exact kind of thing you want to avoid.
In trivial examples, where all of the registrations are made in a single function in a single package, there is clarity around the intention of registration order. But you can't assume that that is how these things will always happen. In fact, for any sufficiently large codebase, these registrations will likely be happening in more than one location, and may be the result of reading input files or generated code where the person writing the spec for the generated code is unaware of the intricacies of execution order and how that may impact routing. It also means that changing the lexical sort of a set of package imports could result in an unexpected change in routing.
Avoid unexpected results, making refactoring easier, and generally trying to make a complex program easier to reason about, are definitely very Go. You might not always agree with their choices, but those are their reasons and they are remarkably consistent.
Re: Better HTTP server routing in Go 1.22
#18I'd prefer the type safety of verb-specific methods (i.e. mux.Get, mux.Post etc) than magic strings validated at run time. Additionally editors can autocomplete/intellisense methods.
Re: Better HTTP server routing in Go 1.22
#19I don't like this. Is there a reason for using a stringified method prefix? I'd prefer the type safety of verb-specific methods (i.e. mux.Get, mux.Post etc) than magic strings validated at run time. Additionally editors can autocomplete/intellisense methods.
Re: Better HTTP server routing in Go 1.22
#20Good one less external dependency. As a side note sqlc + postgres + templ (kindah jsx for go) + htmx + tailwinds has being extremely productive stack to develop in