Go Panic Recovery and Custom Error Generation
When a Go program encounters a severe execution fault, such as an integer division by zero, the runtime triggers a panic, immediately halting execution and printing a stack trace.
package main
import "fmt"
func ExecuteDivision() {
numerator := 42
denominator := 0
outcome := numerator / denominator
fmt.Println(outcome)
}
Executing the above function yields a runtime crash:
panic: runtime error: integer divide by zero
goroutine 1 [running]:
main.ExecuteDivision()
/main.go:8 +0x11
...
Intercepting Panics with defer and recover
To prevent a panic from terminating the entire application, Go provides the recover built-in function. When called within a deferred function, recover stops the panicking sequence, captures the error value passed to panic, and allows the program to resume normal executoin.
package main
import "fmt"
func SafeDivision() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Panic successfully intercepted:")
fmt.Println("Error detail:", r)
} else {
fmt.Println("Execution completed without issues.")
}
}()
numerator := 42
denominator := 0
outcome := numerator / denominator
fmt.Println(outcome)
}
Output:
Panic successfully intercepted:
Error detail: runtime error: integer divide by zero
Returning Safe Defaults After Recovery
If a function needs to return a value even when a panic occurs, named return values can be modified inside the deferred recovery block.
- Define the function with named return variables.
- Assign a fallback value to the named variable within the
recoverlogic.
package main
import (
"fmt"
)
func SafeDivisionWithDefault() (result int, err error) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
result = -1
}
}()
numerator := 42
denominator := 0
result = numerator / denominator
return result, nil
}
Calling SafeDivisionWithDefault will return -1 and <nil> instead of crashing.
Defining and Triggering Custom Errors
For business logic violations where standard error handling is preferred, the errors.New function creates custom error messages.
package main
import (
"errors"
"fmt"
)
func ValidateAge(age int) (int, error) {
if age < 0 {
return 0, errors.New("age cannot be negative")
}
return age, nil
}
When a custom error indicates an unrecoverable state that must stop the application immediately, the error can be passed directly to panic.
package main
import (
"errors"
"fmt"
)
func ProcessAge(age int) {
_, err := ValidateAge(age)
if err != nil {
fmt.Println("Validation failure:", err)
panic(err)
}
fmt.Println("Age is valid")
}
Invoking ProcessAge(-5) prints the validation failure message and then triggers a panic with the custom error, terminating the program.