This was actually more challenging to respond to than I thought it would be.

In Go (as the blog post that I linked alludes to): "The convention in the Go libraries is that even when a package uses panic internally, its external API still presents explicit error return values."

However, it is not the expectation that libraries should recover from panics they didn't start themselves. If they did, it would be very hard to panic and actually have a natural expectation that your application would exit due to that panic, which is how most Go code behaves and expects to behave.

As I wrote in another reply, neither the main goroutine/function nor spawned goroutines automatically recover from panics. They DO shut down the entire server if any code in them panics (provided that no boiler plate recovery is performed at the root of the call stack, which in itself would make it very, very hard to reason about the consistency of the data that might have been touched before panicking at any one of countless of operations in the code in the call stack).

Therefore, one might also argue: Should the entire server shutdown if any worker thread causes a panic? I do agree that it is more plausible for an HTTP request thread to do so, but not enough to change such a basic behavior. Go doesn't allow to register a global panic handler to be able to perhaps recover but also log panics in a consistent way, such that it would be applied consistently across your entire process and customizable to the preferences of the developer as to their chosen trade off between "fail fast/never continuing processing in the face of unexpected programming errors" and "an unexpected programming error occurred but I still want to continue executing and hope that nothing broke in my application".

And I do acknowledge that different developers/organizations would want to make that trade off differently, but at present it is not very convenient to do consistently. The Go creators chose not to allow global panic handles (there are a bunch of discussions about it on Google Groups and similar, and I do agree with some of the arguments in them).

Some people (myself included) might prefer that the application fails and whatever orchestration manages this application triggers an alarm with operations staff, developers, etc, without instead risking that an application keeps running and perhaps due to some invariant now being violated and data inconsistent keeps making mistakes, perhaps serious mistakes.

This of course depends a lot on what kind of application you're building and how important this is, how much uptime for partial (but potentially buggy) functionality weighs against never risking serious mistakes. I tend to think that the correctness of most software in the world is actually important these days, but I fully admit there's a scale. Go however is being used to build all kinds of software these days.

If one doesn't like that strategy, and wants to build software that recovers in other fashions then perhaps one should have a look at Erlang and its process supervisor trees, or other systems with other trade offs.

It is a genuinely hard question, I admit that. I just don't think Go's stdlib in this case chooses a position on that trade off that I like, that's all. It's all opinion, and we're all entitled to them. Thanks for asking, and forcing me to put thoughts into words!