Compile errors vs runtime panics
Go checks your program twice. First the compiler reads every file in the package and refuses to build a binary if anything is wrong with the syntax, the types, or the names — including things other languages only warn about, such as an unused variable or import. Then the runtime executes the binary, and problems that depend on real data — a nil pointer, an index past the end, a channel closed twice — stop the program with a panic. go run main.go does both steps, so you see either kind of message in the same terminal.
Compile error (go build / go run)
- Nothing runs at all — not even the first line of
main - Starts with
# command-line-arguments(the package being built) - Format:
./main.go:6:2: message— file, line, column - Always reproducible: same code, same error
Runtime panic
- The program started, maybe printed some output, then stopped
- Starts with
panic: …orfatal error: … - Followed by a goroutine trace and
exit status 2 - Depends on the input: it may work for one value and crash for another
Anatomy of a compile error
# command-line-arguments
./main.go:8:11: invalid operation: count * price (mismatched types int and float64)The package being built, then file:line:column, then the message. Go editors turn this into a red underline at exactly that column.
- Fix the first error first. The compiler stops after about ten errors, and one mistake (a missing brace, a misspelled type) often causes several of them.
- Go errors are short and literal.
declared and not used: totalmeans exactly that. Read the message word by word before searching for it. - The column matters.
9:21points at the argument that has the wrong type, not just the line.
Anatomy of a panic: read the goroutine trace bottom-up
This program totals the prices of an order. One item is "abc", strconv.Atoi fails and returns 0 (the error was ignored with _), and 100 / n divides by zero:
package main
import (
"fmt"
"strconv"
)
type Order struct {
Items []string
}
func priceOf(item string) int {
n, _ := strconv.Atoi(item)
return 100 / n
}
func total(o Order) int {
sum := 0
for _, it := range o.Items {
sum += priceOf(it)
}
return sum
}
func main() {
o := Order{Items: []string{"4", "5", "abc"}}
fmt.Println(total(o))
}panic: runtime error: integer divide by zero
goroutine 1 [running]:
main.priceOf(...)
./main.go:14
main.total({{0x7f543ee96e68?, 0x7f543edb41e0?, 0x7f543ee96e98?}})
./main.go:20 +0x7c
main.main()
./main.go:27 +0x50
exit status 2The real output (temp-dir paths shortened to ./main.go). The newest call is at the top, main.main is at the bottom.
- 1Read the first line
panic: runtime error: integer divide by zerois the whole diagnosis. The words afterpanic:are what went wrong. - 2Find the goroutine that crashed
goroutine 1 [running]is the main goroutine. In a program with many goroutines, the first one listed is the one that panicked; the word in brackets (running,chan send,chan receive) is what it was doing. - 3Start at the bottom: main.main
Each frame is two lines: the function, then
file:line. The bottom frame is where your program started —mainat line 27 calledtotal. - 4Read upward to the crash
totalat line 20 calledpriceOf, which crashed at line 14. Reading bottom-up tells the story of how the bad value travelled; the top frame in your code is where to put the fix. - 5Ignore the noise
(...)means the function was inlined; the hex numbers are argument words and the+0x7cis an offset in machine code. Frames under/usr/local/go/src/are the standard library — almost never the bug.
The real bug is not on line 14 — it is on line 13, where the error from strconv.Atoi was thrown away. That is the usual shape: the panic line is where the program noticed, one of the frames below it is where the mistake was made. Module 07 shows how to return the error instead.
panic: can be stopped by recover() in a deferred function. A fatal error: (deadlock, concurrent map writes, out of memory) cannot — the runtime decided the program is in a state it must not continue from. Set GOTRACEBACK=all to see every goroutine, not just the one that crashed.