21.6 When panic Is Appropriate and When to Return Errors Instead

Look, let’s get one thing straight: panic is your program screaming “I CAN’T EVEN” and noping out of existence. It’s the nuclear option. For 99% of the errors your code will encounter, you should be using the polite, dignified method of returning an error value. It’s the difference between a waiter gracefully telling you the kitchen is out of the salmon and the same waiter bursting into flames because you asked for extra lemon.

21.5 Converting Panics to Errors: The Pattern

Right, so you’ve decided you want to handle panics. Good for you. Most of the time, letting your program just explode and dump a stack trace to some poor user’s terminal is a pretty terrible user experience. It’s the programming equivalent of just walking away mid-conversation. Rude. But you can’t just recover anywhere. That’s the first and most important thing to understand. The recover function only does anything useful when it’s called inside a deferred function. And not just any deferred function—one that’s running because a panic is currently unwinding the stack. Outside of that context, recover returns nil and does absolutely nothing. It’s a superhero that only works in its own specific comic book universe.

21.4 Using Recover to Prevent Library Panics from Crashing Callers

Right, so you’ve decided you don’t want your library to be the reason someone else’s production service goes down in a ball of flames. Good call. A panic bubbling up from your code into a caller you don’t control is the professional equivalent of setting off a fire alarm and then leaving the building. It’s rude, unprofessional, and leaves everyone else to deal with the mess. The escape hatch for this specific problem is recover. It’s Go’s panic button, literally. You use it inside a defer to catch a panic that’s happening on the same goroutine. Think of it as a net that you stretch out below you just as you’re about to jump. If you don’t jump, the net just hangs there, useless. If you do jump, it catches you before you hit the ground and splatter all over the innocent pedestrians below (your callers).

21.3 recover: Catching a Panic in a Deferred Function

Right, so you’ve met panic. It’s the language’s built-in fire alarm, and it’s meant for genuine catastrophes, not your average Tuesday. But sometimes, even in a well-tested system, a catastrophe happens. Maybe a third-party API sends back nil where you expected a complex data structure. Maybe you divided by a user-supplied value that, against all odds, was zero. When that panic rips through your call stack, shutting down everything in its path, you might want a safety net. That’s where recover comes in.

21.2 Runtime Panics: Index Out of Range, Nil Dereference

Right, let’s talk about panic. It’s the moment your Go code throws its hands up in the air and says, “I’m out, you deal with this.” It’s not an error; it’s a full-blown, runtime-stopping tantrum. And the two most common ways you’ll accidentally trigger one are by reaching for something that isn’t there (index out of range) or by trying to use nothing as if it were something (nil dereference). These aren’t gentle reminders; they’re a brick wall.

21.1 panic: Signaling Unrecoverable Errors

Right, let’s talk about panic. You’ve probably seen it. The program stops, a bunch of red text vomits all over your terminal, and you feel a brief moment of pure, unadulterated shame. Don’t. A panic is how Go tells you, in no uncertain terms, that something has gone so fundamentally sideways that it cannot possibly continue executing your code with any integrity. It’s the runtime’s version of throwing its hands up and saying, “I’m out. You deal with this.”

— joke —

...