Panicking: Should you avoid it?
The short answer is: "yes".
The long answer is: "it depends", i.e., it depends on what you mean by "avoiding".
In general, it is advisable to try handling errors as hard as you can. This entails returning semantic types indicating error conditions, e.g. Result
for denoting the failure of a fallible operation or Option
for representing the absence of a value or meaningful answer.
You shouldn't generally "trust" users or their input and assume that only the happy path will occur. When you are designing some code, and especially in the presence of external-facing APIs, you should make it hard or ideally impossible for your code to be used incorrectly. People won't expect your code to panic. In fact, nobody expects code to hit control flow that is not apparent from the structure of the code – this is why implicitly-thrown, untyped "exceptions" cause preposterous errors and dormant bugs in languages without real error handling.
Furthermore, panics can't be caught reliably even if you do remember them (e.g. panic = "abort"
profiles). This means that if you decide you want to panic on error, you have completely taken away the ability of graceful error handling from downstream consumers of the code. This is, needless to say, Bad™, and you shouldn't design your APIs like that by default.
However, in general, it's not possible to always avoid panicking. Maybe you are yourself a consumer of a bad API that just panics left and right, or you have an invariant in your code that is impossible to encode in the type system, so you can't have the compiler prove that "element at index 1 will always exist", or something like that. In this kind of situation, it's better to panic than to silently misbehave. It's better to have your program crash cleanly at the determinate point where it performed an invalid operation, than have it access uninitialized memory, return garbage answers, or accidentally launch the nukes.
So, sometimes, panicking is the better alternative. But that's a pretty rare special case that you shouldn't be hitting too often. Try to use the type system for upholding invariants as your first attempt, and only if that doesn't work out, resort to runtime checking and panicking.