Recover in Golang

In this tutorial, you will learn about recovery and panic in Golang. Before starting this tutorial make sure you know about the concept of panic which we discussed in our last tutorial.

What is recover in Golang?

A recover function is a built-in function used to recover from a panicking situation in the Go programming language. So even if a panic occurs in a go program it is able to recover from that panic and continue its normal execution. This is the significance of the keyword recover.
Let us start to learn through a panicking program given below


package main
import "fmt"

func main() {
 fmt.Println("lets learn about recover() in golang")
 Panicfunc()
 fmt.Println("learned all about recover() ")
}
func Panicfunc() {
 fmt.Println("instruction just before panicking situation")
 panic("Panicfunc terminates from execution")
 fmt.Println("instruction after panic does not execute")
}

Output:


lets learn about recover() in golang
instruction just before paniciking situation
panic: Panicfunc terminates from execution

goroutine 1 [running]:
main.Panicfunc()
 /tmp/sandbox1636989584/prog.go:13 +0x65
main.main()
 /tmp/sandbox1636989584/prog.go:7 +0x5b

Program exited.

A panic function is an exception in Golang where the program terminates from its normal execution without knowing what to do next by leaving an error message either passed by the programmer as arguments using the inbuilt panic function or by default during runtime.
The given program consists of two functions one is main() and other is Panicfunc().
When the program begins its execution from the main function it executes the first instruction to print let's learn about recover() in golang.

fmt.Println("lets learn about recover() in golang")

The main function scans the next instruction to execute which is a function called Panicfunc().The control switches to Panicfunc() where a set of instructions are executed. The first instruction which is given below is executed and prints
the instruction just before a panicking situation.
fmt.Println("instruction just before panicking situation")

panic("Panicfunc terminates from execution")

The program terminates with the below instruction when it finds panic function and results in printing that string i.e. panic: Panicfunc terminates from execution and leaves some stack trace.

How to use recover function in the panic program?

Let us continue with the same code discussed above but some new codes are added to it.
A new function called Panicrecover is added to the above code in which a predefined recover() function is used. 


func Panicrecover() {
 if err := recover(); err != nil {
  fmt.Println("Recovered from panic \n", err)
 }

In order to resume the normal flow of execution, we need to add defer function inside the Panicfunc ().
To understand the significance of defer refer tutorial we have already covered. Recover is useful within deferred functions. So if you want to use Panicrecover function (recover ()) inside panicking function ie in our example Panicfunc  you need to call defer function which states

defer Panicrecover()

Let us recap the idea of defer.
Any functions which are deferred (delayed) are known as defer functions which are called just before enclosing the function. In our program, the above-given code will defer the function recover.

In this program when a panic occurs then the Panicfunc is called to recover by calling the Panicrecover function. Inside the Panicrecover function, we have a call to inbuilt recover(), which allows the normal flow of the program. The execution is picked up from the Panicfunc() function which is called by main ().
 Let us check the whole code 


package main
import "fmt"

func main() {
 fmt.Println("lets learn about recover() in golang")
 Panicfunc()
 fmt.Println("learned all about recover() ")
}

func Panicfunc() {
 defer Panicrecover()
 fmt.Println("instruction just before panicking situation")
 panic("Panicfunc  resume  execution")
 fmt.Println("instruction after panic does not execute")

}
func Panicrecover() {
 if err := recover(); err != nil {
  fmt.Println("Recovered from panic \n", err)
 }
}

Output:


lets learn about recover() in golang
instruction just before panicking situation
Recovered from panic 
Panicfunc  resume  execution
learned all about recover() 

Program exited.

The flow of control in a program

GO : Recover

Let us summarize the flow chart given above

  •   The program begins its execution from the main function prints the first statement   lets learn about recover() in golang
  •   Then Panicfunc() runs it defers a function Panicrecover().
  •   The Panicfunc prints instruction just before the panicking situation
  •   Then the function starts panicking but before that it executes the deferred function.
  •   The defer function calls recover () function
  •   Since this is context to the panicking situation the return type checked if the error is not equal to nil prints Recovered from panic continued with message return by panic.
  •   The execution return backs to main function and prints learned all about recover() 
  •   This is the procedure followed by recover function to overcome a panicking situation.

Does the recover function return a nil value?

Yes, the recover function returns a nil value during normal execution.
Consider the same code discussed above by omitting the panicking situation. Just discard the 

panic("Panicfunc  resume  execution")

The code looks like below


package main
import "fmt"

func main() {
 fmt.Println("lets learn about recover() in golang")
 Panicfunc()
 fmt.Println("learned all about recover() ")
}

func Panicfunc() {
 defer Panicrecover()
 fmt.Println("instruction just before panicking situation")

 fmt.Println("instruction after panic does not execute")

}
func Panicrecover() {
 if err := recover(); err != nil {
  fmt.Println("Recovered from panic \n", err)
 }

}

Output:


lets learn about recover() in golang
instruction just before panicking situation
instruction after panic does not execute
learned all about recover() 

Program exited.

In the above program, the control flows normally. There is nothing to recover from the recover function, no panicking situation so it returns a nil value.
Better understand the below program with recover function containing an else part that states the recover function returns a nil value.


package main
import "fmt"

func main() {
 fmt.Println("lets learn about recover() in golang")
 Panicfunc()
 fmt.Println("learned all about recover() ")
}

func Panicfunc() {
 defer Panicrecover()
 fmt.Println("instruction just before paniciking situation")

 fmt.Println("instruction after panic does not execute")

}
func Panicrecover() {
 if err := recover(); err != nil {
  fmt.Println("Recovered from panic \n", err)
 } else {
  fmt.Println("Recover a nil value :", err)
 }

}

Output:


lets learn about recover() in golang
instruction just before paniciking situation
instruction after panic does not execute
Recover a nil value : 
learned all about recover() 

Program exited.

Note:

  • Recover is used only in defer functions.
  • A call to recover during normal execution returns a nil value.
  • A recover call to a panicking program will resume its normal execution by identifying the panic statement.