Table of contents
1.
Introduction
2.
Panic
2.1.
Syntax and example of panic
2.2.
Panic Due to Runtime Error
2.3.
Calling the Panic function explicitly.
3.
Defer
4.
Recover 
5.
FAQs
6.
Key Takeaways
Last Updated: Mar 27, 2024

Go Panic and Recover

Author ANKIT KUMAR
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Panic and Recover are part of the Go error handling techniques. For some readers, the concept of Panic and Recover is always very confusing. However, it is not confusing at all. In this article, we will learn all about panic and how we can recover from it.

Panic is equivalent to raising an exception in some other programming languages( like Java), whereas Recover can be thought of as catching the exception.

We shall first discuss panic and then recover.

Panic

Panic is used to exit a program when it detects abnormal conditions.

Panic is a built-in function that causes the normal flow of control to stop and panic to begin. When any function (say f()) calls panic, the execution of function f() is halted, any deferred functions inside function f() are executed normally, and then it returns to its caller.

Panics are generated mainly because of two reasons:

  • Any runtime error, such as index out of bounds error, happens when an index larger or lesser than the size of the array is accessed.
  • If the panic function is explicitly called in the program.

Syntax and example of panic

Syntax:

func panic(v interface{})

Example:

package main


func main() {
    
    panic("Panic is explicitly called.....")
}

Output: 

panic: Panic is explicitly called.....

goroutine 1 [running]:
main.main()
/home/main.go:5 +0x39

Panic Due to Runtime Error

Runtime errors can occur in situations like:

  • Accessing an index in an array that is not available. It is known as an array index out of bounds/range error.
  • When a function is called with a nil pointer.
  • Sending on a closed channel.
  • When there is incorrect type assertion.

Example:

package main


import "fmt"


func main() {
    
    // declare a slice of lenght 2. The contents are
    // Coding and Ninjas
	company := []string{"Coding", "Ninjas"}

	//prints company[0] -> Coding
	fmt.Println(company[0])

	// prints company[1] -> Ninjas
	fmt.Println(company[1])

	// trying to access index 2 which does not exist
	// will result in a panic
	fmt.Println(company[2])
}

Output: 

Coding
Ninjas
panic: runtime error: index out of range

goroutine 1 [running]:
main.main()
/home/main.go:19 +0x12a

Calling the Panic function explicitly.

There are certain situations where the programmers call the panic function explicitly in the program. One of the most common scenarios is when a certain input is expected as a parameter; however, nil is passed. In such a case, the programmer puts a check that if a nil value is passed, raise a panic.

Example: 

package main


import "fmt"


func main() {
    
    //create a slice named company
    company := []string{"Coding", "Ninjas"}
    
    //printing the content of company[] before called noNilAllowed()
    fmt.Println(company[0],company[1])
    fmt.Println() // to add an extra line
    
    //pass nil as the value to noNilAllowed()
    noNilAllowed(nil)
    
}


// function that does not allows nil parameters
func noNilAllowed(company[] string){
    
    if company==nil{
        
        // creating a panic if nil is passed
        panic("Nil value supplied. Program halted!")
    }else{
        fmt.Println("supplied value is: ", company)
    }
}

Output: 

Coding Ninjas

panic: Nil value supplied. Program halted!

goroutine 1 [running]:
main.noNilAllowed(...)
/home/main.go:25
main.main()
/home/main.go:15 +0x13a

Defer

We have studied a lot about panic till now. Before we move on to discuss recover, it is important to get familiar with the defer keyword and its application

Defer statements in Go delay the execution of the function or method or an anonymous method until the nearby functions return. Defer statements are commonly used to ensure that files are closed when their use is no longer required, to close the channel, or to catch panics in the program. 

Example:

package main

import "fmt"

func main() {
    
    //create a slice named company
    company := []string{"Coding", "Ninjas"}
    demonstrateDefer(company)
    
}
func demonstrateDefer(company []string){
    
    fmt.Println("Demonstrating defer!")
    defer fmt.Println(company[0]) // "Coding" is printed at the last
    
    // These three statements are printed before the deferred statements
    fmt.Println("Defer 1")
    fmt.Println(company[1])
    fmt.Println("Defer 2")
    
}

Output: 

Demonstrating defer!
Defer 1
Ninjas
Defer 2
Coding

Explanation:

Using defer keyword with fmt.Println(company[0]), defers the statements, meaning the statement is executed after every other statement in the demonstrateDefer() is executed.

Recover 

Now that we have studied defer, we can easily understand the concept of Recover. In programming languages, in Java we "catch" the exceptions whenever they occur. The recover() function does the same thing. It catches the panic.

Syntax: 

func recover() interface{}

Let us consider an example before we try to understand recover() in more detail.

package main

import "fmt"

func main() {
    
    demonstrateRecover()
    
}
func demonstrateRecover(){
    
    fmt.Println("Inside demonstrateRecover() function...")


    // defer the function that recovers from panic
    //because panic has not occurred till now
    defer recoverFromPanic()
    
    // creates panic
    panic("Panic has occurred")
}

func recoverFromPanic(){
    
    // recovers() returns value that is passed to the panic function
    //if it is not nil, panic has occurred. It needs to be recovered
    // else everything is fine
    
    if r:=recover(); r!=nil{
        fmt.Println("Panic: ",r)
        fmt.Println("resolved")
    }else{ 
        fmt.Println("Everything is fine!")
    } 
}

Output: 

Inside demonstrateRecover() function...
Panic:  Panic has occurred
resolved

Explanation:

The part of the code which is most crucial is:

if r:=recover(); r!=nil{
     fmt.Println("Panic: ",r)
     fmt.Println("resolved")
}else{ 
     fmt.Println("Everything is fine!")
} 

We can ignore the print statements for now. 

The first line will store the value passed by the Recover () function in r. The Recover () function actually returns the same value, which is passed to the panic function. r!=nil checks if the value returned by the Recover () function is nil or not. If it is nil, that means that there has been no panic, or simply we can say that the panic statement was not executed.

If the value of r is not nil, it means that there is some value in r, and that value is returned by Recover (), which is nothing but the value passed to the panic function. Therefore we can say that panic has happened.

Depending on the users, there are various ways we would deal with the panic. In the above example, we just acknowledged that panic has occurred and printed the panic value.

FAQs

1.What is panic in Go?

Panic is a built-in function that causes the normal flow of control to stop and panic to begin. 

2. What is Recover () in Go?

Recover is a built-in function in Go that regains control of a panicking goroutine. Recover is only useful inside deferred functions.

3. Why should the recover() function be inside the deferred function?

The only function that gets executed after the panic is the deferred function. Therefore we must put our Recover () function inside the deferred function to ensure that it gets executed.

4. What does the Recover () function return?

The Recover () function returns the same value, which is passed to the panic function.

Key Takeaways

In this article, we have extensively discussed Panic and Recover in Go programming language along with their code implementation.

  • Panic is a built-in function that causes the normal flow of control to stop and panic to begin. 
  • The Recover () function returns the same value, which is passed to the panic function. It is used to deal with panics.
  • We must put our Recover () function inside the deferred function to ensure that it gets executed.

We hope that this blog has helped you enhance your knowledge regarding Panic and Recover and if you would like to learn more, check out our articles here. Do upvote our blog to help other ninjas grow. Happy Coding!

Live masterclass