How to Dump Goroutine Stack Traces in Go
The idiomatic approach to dealing with strange circumstances is to use errors in a Go program. Errors cause the majority of the unusual cases that arise in the software.
However, in rare cases, the software will not be able to continue running due to an aberrant state. In this situation, panic
can end the program early.
When a function encounters a panic
, the function’s execution will halt, any delayed functions will run, and control will return to the function’s caller.
This procedure continues until all of the current goroutine’s functions have returned, at which time the program prints the panic
message, then the stack trace, before terminating.
When we construct an example program, this will become clearer.
Use panic
to Dump Goroutine Stack Traces in Go
This simple script will print a person’s full name. The fullName
function returns a person’s complete name.
This method checks for nil
values in the firstName
and lastName
pointers. If it’s nil
, the function sends a panic
signal with a message.
When the program finishes, it will print this message.
package main
import (
"fmt"
)
func fullName(firstName *string, lastName *string) {
if firstName == nil {
panic("runtime error: first name cannot be nil")
}
if lastName == nil {
panic("runtime error: last name cannot be nil")
}
fmt.Printf("%s %s\n", *firstName, *lastName)
fmt.Println("returned normally from fullName")
}
func main() {
firstName := "Jay"
fullName(&firstName, nil)
fmt.Println("returned normally from main")
}
Output:
panic: runtime error: last name cannot be nil
goroutine 1 [running]:
main.fullName(0x405058?, 0xc000070f70?)
/tmp/sandbox885911142/prog.go:12 +0x114
main.main()
/tmp/sandbox885911142/prog.go:20 +0x35
Now, the below example makes the common mistake of attempting to access the slice’s final element using its length provided by the built-in len
.
To demonstrate why this might induce panic
, run the following code.
package main
import (
"fmt"
)
func main() {
names := []string{
"Iron Man",
"Thor",
}
fmt.Println("My favorite superhero is:", names[len(names)])
}
Output:
panic: runtime error: index out of range [2] with length 2
goroutine 1 [running]:
main.main()
/tmp/sandbox2746930010/prog.go:12 +0x1b