Which common Go operations raise a runtime panic, and what kind of value does the runtime panic with?
answer
- the language refuses, so it fails loudly
- memory safety and type safety violations
- read is fine, write is not, for one type
- the message starts with a fixed prefix
- the value satisfies an interface in runtime
basics
~20 sMemory- and type-safety violations panic: dereferencing a nil pointer, indexing or slicing out of range, integer division by zero, a failed single-value type assertion, writing to a nil map, and closed-channel misuse. The runtime panics with a value satisfying the runtime.Error interface.
solid answer
~50 sThe runtime raises a panic when a program does something the language cannot let it do: dereference a nil pointer, index a slice, array or string out of range, take a slice with bounds outside capacity, divide an integer by zero, perform a single-value type assertion that fails, write to a nil map, or send on and close an already-closed channel. Each of these panics with a value that satisfies `runtime.Error` — an interface that embeds `error` and adds a marker method — so the message usually reads `runtime error: index out of range [5] with length 3` or `runtime error: invalid memory address or nil pointer dereference`. Mechanically these behave exactly like an explicit `panic(v)`: the goroutine unwinds, deferred calls run, and an unrecovered one crashes the process with exit status 2. They exist because Go guarantees memory safety and must fail loudly rather than read past a slice.
code
go · 9 linesvar m map[string]int
n, ok := m["missing"] // fine: n == 0, ok == false
_ = n
_ = ok
m["a"] = 1 // panic: assignment to entry in nil map
s := []int{1, 2, 3}
i := 5
_ = s[i] // panic: runtime error: index out of range [5] with length 3go deeper
Memorise the short list of operations that panic — nil dereference, index out of range, divide by zero, failed type assertion, nil-map write — and the paired facts that reading a nil map and receiving from a closed channel are both safe.
Explain that the runtime panics with a value satisfying runtime.Error, recognise the runtime error: message prefix, and describe how bounds checks make indexing memory-safe and where the compiler can elide them.
Show that you read these messages fast in production: the index and length in a bounds panic, the two type names in an interface-conversion panic, addr=0x0 on the signal line for a nil dereference. Then argue the fix is validation or comma-ok, not interception.
Take a position on where panicking is acceptable in code your organisation ships, and on the review rules that keep unvalidated input from turning a programmer-error mechanism into your service's normal failure mode.
## The catalogue Go has no exceptions, so a runtime panic is the only thing that happens when the program asks for something the language refuses to do. The everyday members of the catalogue: | Operation | Message | |---|---| | Dereferencing a nil pointer, or calling a method on a nil interface value | `runtime error: invalid memory address or nil pointer dereference` | | Indexing a slice, array or string out of range | `runtime error: index out of range [5] with length 3` | | Slicing beyond capacity | `runtime error: slice bounds out of range [:5] with capacity 3` | | Integer division or modulo by zero | `runtime error: integer divide by zero` | | A failed single-value type assertion | `interface conversion: interface {} is string, not float64` | | Writing a key to a nil map | `assignment to entry in nil map` | | Sending on a closed channel | `send on closed channel` | | Closing an already-closed or a nil channel | `close of closed channel`, `close of nil channel` | | Calling a nil function value | `runtime error: invalid memory address or nil pointer dereference` | Note what is *not* here. Reading from a nil map is fine — it yields the zero value and `ok == false`. `len` and `range` over a nil slice are fine. Receiving from a closed channel is fine — it yields the zero value with `ok == false`. Go panics on the operations that would otherwise corrupt memory or silently invent data, not on every use of a zero value. ## The value the runtime panics with The panic value is not a plain string. The runtime panics with a value satisfying: ```go // package runtime type Error interface { error RuntimeError() } ``` `runtime.Error` embeds `error`, so the value has an `Error() string` method, and adds a marker method that distinguishes runtime-generated panics from anything user code panicked with. A failed type assertion, for example, panics with a `*runtime.TypeAssertionError`, which carries the interface type, the concrete type present and the type asserted — which is why its message can name both types. Code that intercepts a panic can type-assert the value to `runtime.Error` to tell "the runtime caught a bug in my program" from "some library called `panic("...")` deliberately". Most of these messages begin with the literal prefix `runtime error: `, which is a useful grep target in logs. ## Mechanically identical to an explicit panic Once raised, a runtime panic behaves exactly like `panic(v)` written by hand. The goroutine stops at the offending expression, its deferred calls run in reverse order, the frame is popped, the caller's deferred calls run, and so on to the top of that goroutine. If nothing stops it, the runtime prints the value and a stack trace to standard error and exits the process with status 2. Nothing about a runtime panic is special-cased in the unwinding machinery. One diagnostic detail is worth memorising: a nil dereference that crashes the process also prints a signal line, `[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x...]`. Go relies on the hardware fault for the nil check on ordinary loads and translates the resulting signal into a panic. `addr=0x0` is the confirmation that the pointer really was nil rather than wild. ## Why bounds checks are there at all Every slice index compiles to a comparison against the length followed by the load. That check is what makes `s[i]` memory-safe, and the compiler removes it where it can prove the index is in range (a `for i := range s` loop, for example). The cost of the remaining checks is small; the benefit is that an off-by-one becomes a loud panic with a file and line rather than a silent read of neighbouring memory. Trying to defeat this with `unsafe` gives up the guarantee entirely. ## The design line Go's convention is that **expected** failures are `error` values a caller checks — a file that does not exist, a malformed request, a timed-out call — while **impossible** conditions panic. Indexing past the end of a slice is not an expected outcome you handle; it is a bug in the code that computed the index. The right response is almost never to intercept the panic and continue; it is to validate the input, check the pointer, or use the comma-ok form of the operation where one exists (`v, ok := x.(T)` for assertions, `v, ok := m[k]` for map reads) so the failure becomes an ordinary branch instead of a crash.
- How can code that intercepts a panic tell a runtime panic from one a library raised deliberately?Type-assert the panic value against `runtime.Error`. That interface embeds `error` and adds a marker method, and only values the runtime itself raises satisfy it. A library's `panic(errors.New("..."))` or `panic("...")` will not, so the assertion cleanly separates "my program has a bug" from "this component chose to abort".
- Why does reading a missing key from a nil map succeed while writing to it panics?A nil map has no hash table backing it. A read has an obvious, safe answer — the value type's zero value with `ok == false` — so the language defines it. A write has nowhere to put the entry and would require the runtime to silently allocate a map the caller never asked for, so it panics with `assignment to entry in nil map`.
- Does a failed type assertion always panic?Only the single-value form does: `v := x.(T)` panics with a `*runtime.TypeAssertionError` naming both types. The comma-ok form, `v, ok := x.(T)`, never panics — it yields the zero value of `T` and `ok == false`. Reaching for the comma-ok form is the standard fix when the dynamic type is not guaranteed.
saying these in an interview costs you the question
- Says reading from a nil map panics
- Thinks a panic value is always a plain string
- Claims out-of-range indexing is caught at compile time
- Believes the comma-ok type assertion can panic
- Confuses receiving from a closed channel with sending