You can't guarantee the order of registration will always be the same, so it's really undefined behavior. This is how the original ServeMux was designed and implemented, and they felt that was useful behavior to continue to support.
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.
From the design proposal[1]:
See also the background discussion[2]: [1]: https://github.com/golang/go/issues/61410 [2]: https://github.com/golang/go/discussions/60227