According to Go's specifications:
While executing a function F, an explicit call to panic or a run-time panic terminates the execution of F. Any functions deferred by F are then executed as usual. Next, any deferred functions run by F's caller are run, and so on up to any deferred by the top-level function in the executing goroutine. At that point, the program is terminated and the error condition is reported, including the value of the argument to panic. This termination sequence is called panicking.
This means that if a goroutine panics and is not recovered, the application terminates.
Aside from the fact that an unhandled panic can be an easy bug to miss, this also puts my application at the mercy of imported packages which may start goroutines with unhandled panics. If an imported package panics in this way, my application will terminate and, as far as I am aware, there is no way to recover.
In a production environment, keeping my application alive is mission-critical, and this behavior poses a problem. My question is twofold:
- What is the "philosophical" idea behind this design choice? Why did Go developers decide to omit isolation between lifecycles of goroutines?
- Is there some way that I missed to keep goroutines alive in the case where a different goroutine panics?