When to use os.Exit() and panic() (plus exit codes)?

os.Exit() and panic() seem similar but are definitely not and shouldn't be used interchangeably.


os.Exit() exits the program immediately with the given status code. It should be used when we want to exit the program. There are two usual cases where I use os.Exit():

  1. on invalid user input (like HTTP 400)
  2. on application error (like HTTP 500)

os.Exit() is most commonly used in CLI programs. It is a way to interact with the user; print a helpful message and exit. I think of it as a 4xx/5xx status code in HTTP.


panic() is like returning the current and all its parent functions. Along the way while it's doing that, it runs deferred functions. When all the functions return, the program has nothing more to do. As such, it prints the stack trace and dies.

Printing the stack trace isn't exactly good user experience. Based only on that, it's obvious that panic shouldn't be used under normal circumstances.

Panic is aptly named—we call it when the program or rather we don't know how to continue and panic. Only when we reach an "impossible" point in a program, should we ever panic.

The most common panics are called implicitly for run-time errors. We have all encountered an out of bounds panic. (It is called when we try to access an element in a slice whose index is beyond the slice's length.) This is an "impossible" case where panic should be used.

I predominantly use panic for asserts—to test that state is correct (to make invariants explicit).

Exit codes

Exit codes indicate how a process exited. Conventionally, 0 indicates success and non-zero an error.

There are three codes we need to know about:

Note that there is no standard and the exit codes are not consistent across programs.

Panic exits with code 2 which is unusual. There is an open issue about it: runtime: wrong Unix error code from panic. But even if the exit code will change, it seems that Go would only document the code as non-zero and not explicitly.

You can see this page's source written in Touch and the config used.