Golang Tutorial
Introduction Variables Constants Data Type Convert Types Operators If..Else Switch..Case For Loops Functions Variadic Functions Deferred Functions Calls Panic and Recover Arrays Slices Maps Struct Interface Goroutines Channels Concurrency Problems Logs Files and Directories Reading and Writing Files Regular Expression Find DNS records Cryptography Gotchas in Golang Import and Export Best Golang Packages Web Application Goroutines and Channels Exercises Reflection in Golang Golang for beginners Strings in Golang HTTP Client Server Examples Context PackageGolang Reference
Basic Programs Advance Programs Data Structure and Algorithms Date and Time Slice Sort, Reverse, Search Functions String Functions Methods and Objects Interface TypeBeego Framework
Beego Setup Beego Database Migration Beego GET POST Beego RoutingGolang Panic and Recover Tutorial with Examples
Panic and Recover
In Go (Golang), a panic is a mechanism that allows you to halt the normal execution of a program when an unexpected or unrecoverable situation occurs. It is similar to an exception in other programming languages. When a panic is triggered, the program starts to unwind the call stack, running any deferred functions that are associated with each function call, and then crashes with a log message describing the cause of the panic.
The signature of the panic() function is as follows:
func panic(v interface{})
The panic() function takes a single argument v of the empty interface type (interface{}). This means that you can pass any value of any type as an argument to panic(). When a panic is triggered, the provided value is typically used to describe the reason for the panic, such as an error message or an error object.
Example of using panic() in Go
For example, let's say you are developing an application that processes sensitive information, and it requires a specific configuration file to work correctly. If the file is not found or is malformed, it's better to terminate the program immediately rather than continuing with incorrect or incomplete data.
Here's an example of using panic() without recover():
Example
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type Config struct {
SecretKey string `json:"secret_key"`
}
func main() {
// Read configuration file.
configData, err := ioutil.ReadFile("config.json")
if err != nil {
// If there's an error reading the file, panic and terminate the program.
panic(fmt.Sprintf("Error reading configuration file: %v", err))
}
var config Config
err = json.Unmarshal(configData, &config)
if err != nil {
// If there's an error unmarshaling the JSON data, panic and terminate the program.
panic(fmt.Sprintf("Error parsing configuration data: %v", err))
}
if config.SecretKey == "" {
// If the secret key is empty, panic and terminate the program.
panic("Secret key is missing from configuration")
}
// Continue with the program execution.
fmt.Println("Application started successfully.")
}
In this example, if the configuration file is missing, cannot be read, or the JSON data is malformed, the program will panic and terminate immediately. This ensures that the application doesn't continue with an invalid configuration, potentially causing data leaks or other issues.
However, this type of usage should be reserved for critical errors, and you should always strive to handle errors gracefully whenever possible.
panic: Error reading configuration file: open config.json: no such file or directory
goroutine 1 [running]:
main.main()
/tmp/sandbox1728768757/prog.go:18 +0x179
Example of using recover() in Go
recover() is a built-in function in Go that is used to regain control of a panicking goroutine. When a panic() is called, the normal flow of the program is interrupted, and the deferred functions in the same goroutine are executed. You can use recover() within a deferred function to catch the panic value, handle the error, and prevent the program from crashing.
The recover() function, when called inside a deferred function, returns the value that was passed to panic(). If recover() is called outside a deferred function or if no panic() occurred, it returns nil.The signature of the recover() function is as follows:
func recover() interface{}
The recover() function does not take any arguments, and it returns a value of type interface{}, which is the empty interface in Go. The empty interface can hold values of any type, so it allows recover() to return any value that was passed to the panic() function.
You can modify the given program to use recover() to handle the panic() gracefully. To do this, you can create a deferred function in the main() function that will call recover() and handle the panic scenario.
Example
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
)
type Config struct {
SecretKey string `json:"secret_key"`
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Printf("An error occurred: %v\n", r)
fmt.Println("Application terminated gracefully.")
} else {
fmt.Println("Application executed successfully.")
}
}()
// Read configuration file.
configData, err := ioutil.ReadFile("config.json")
if err != nil {
// If there's an error reading the file, panic and terminate the program.
panic(fmt.Sprintf("Error reading configuration file: %v", err))
}
var config Config
err = json.Unmarshal(configData, &config)
if err != nil {
// If there's an error unmarshaling the JSON data, panic and terminate the program.
panic(fmt.Sprintf("Error parsing configuration data: %v", err))
}
if config.SecretKey == "" {
// If the secret key is empty, panic and terminate the program.
panic("Secret key is missing from configuration")
}
// Continue with the program execution.
fmt.Println("Application started successfully.")
}
In this modified program, we have added a deferred function that will call recover(). If there's a panic, the deferred function will catch the panic value, print an error message, and gracefully terminate the application. If there is no panic, the program will continue execution, and the deferred function will print a success message when it finishes executing.
Running this code produces the following output:
An error occurred: Error reading configuration file: open config.json: no such file or directory
Application terminated gracefully.