Go - Defer, Panic and Recover
Tags: devops, go, beginners, tutorial
Published: 2022-09-28 17:48:41

## Introduction

With the previous part (6), we finished basics in **Go**. Most of the topics covered in those parts are common in most programming languages. By hearing the topics covered in previous parts, we can relate them with other programming languages if we know any. The topics we are going to discuss in this part are **Defer**, **Panic** and **Recover**. I am not sure about the people reading this, but I haven't heard them before learning **Go**. But panic and recover are available in other programming languages as well but with different names. We will talk more about this later. Let's get into this one.

## Defer

The functionality of **defer** is simple. It just delays the execution of a line for some time. Okay....How much time? It delays until all other lines in the function in which the defer line is residing are finished executing.

The syntax to use **defer** is `defer <any valid line>`.'

### Basic example to illustrate defer functionality

```go
package main

import "fmt"

func main() {
	defer fmt.Println("First line code, but comes last in output")
	fmt.Println("Second line in code")
	fmt.Println("Last line in code")
}
```
**Output**:

![Output1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7xvs07ehzhnc1k8dkbz.png)

If you see the output, the line having **defer** printed last even though it is the first line in the function. That is what defer does. It delays the specified line of code until all other lines are executed in that function scope.

### Program to illustrate multiple defer statements in same function

We saw how **defer** works. What if there are more than one defer statements in a function? Which line executes first and which one executes last?

To answer this, we need to understand what actually is happening when the defer line is being delayed. So, when we use **defer** before a line, when the control of program comes there, it pushes the defer line into a stack to store it temporarily. When the function execution comes to end, before it finishes, the lines pushed into the stack are popped out and executed one by one.

If you are aware how a stack works, it is a Last-In-First-Out data structure. Meaning, whichever item is pushed last into it, comes out first. So, in our context, the line which gets pushed into stack last, will get popped out first and executed first. See below code and output to see it practically.

```go
package main

import "fmt"

func main() {
	defer fmt.Println("First line") // goes first into defer stack
	defer fmt.Println("Second line") // goes last into defer stack
	fmt.Println("Third line")
	fmt.Println("Last line")
}
```
**Output**:

![Output2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ayil6q7l8wuz67ixc25.png)

In the above program, "First line" goes first into defer stack and "Second line" goes last. But in the output, after "Third line" and "Last line" got executed, "Second line" is executed first because it is the last line pushed into the stack.

### Program to illustrate the variable values evaluation at defer line

I know the heading of this section is confusing. Even I don't understand what I have written. But just bear with me for this section.

Consider this situation where there is a variable in a function and that is being printed in a line. But there is a **defer** keyword before that line. After that line, we are changing the value of that variable. So, what value does the defer line prints? Initial value or Changed value? The line is using variable before changing the value. But also the line is being executed after changing the value. So, what value does it print?

The simple answer is when a defer line is pushed into the defer stack, it pushed along with the values of variables it is using but not the actual variable itself. So, no matter what happens to that variable after the line, the initial value is already pushed into defer stack along with defer line. Hence, it prints initial value.

I hope you understand the heading for this section a bit now.

```go
package main

import "fmt"

func main() {
	testVar := 10
	defer fmt.Println("The value is: ", testVar) // should print 10 because the value is already evaluated
	testVar += 1
}
```
**Output**:

![Output3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwgxqr860gi3tk175zt0.png)

## Panic

This word is something unique to this **Go** language but the concept is not. We call these as **exceptions** in other languages. Yeah so, basically if any runtime error happens while executing a code, it creates **panic** in the execution and the executions terminates abruptly.

If you are already familiar with runtime errors, then fine. If not, just consider them as unexpected errors those may occur while program is running. A simple such error can be occurred during dividing two numbers. Consider a situation where we are taking input from user for two number and divide one with the other. If the user gives denominator as 0 and we divide with 0, it throws a runtime error. This creates panic in the execution and execution stops no matter if there is code after it.

### Program to create panic by dividing with 0

```go
package main

import "fmt"

func main() {

	var a int
	var b int
	fmt.Scan(&a) // input 1
	fmt.Scan(&b) // input 2
	c := a / b   // division

	fmt.Println(c)
}
```
**Output**:

![Output4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/05d1awkgxq807nkywy6w.png)

As you can see, since I have give second input as 0 and it divides with 0, the execution panics. Even though there is a print statement after that line, it won't execute it.

So, can a runtime error only create panic? No, we can create panic on our own using **panic** keyword. This is just like throwing errors in other languages.

### Program to illustrate panic keyword

```go
package main

import "fmt"

func main() {
	fmt.Println("This line prints fine since it is before panic")
	panic("Panicking just for fun")
	fmt.Println("This line won't get printed since it is after panic")
}
```
**Output**:

![Output5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5siyjk1dnqy3qbfuq1uv.png)

Why are we creating panic for fun? We definitely don't do it for fun. But, I am not getting any idea on top of my head to justify that we don't do it for fun. I will write another article if I find one. Or you can comment down if you have ever thrown an error in code in a serious use-case.

## Recover

In real world code bases, there are multiple functions running one after the other. If we some panic is being created in one function stops entire code execution, the next functions won't even run. We don't want it in most situations. For that we need a way to avoid stoppage of code execution even if panic happens.

This is where **recover** comes into picture. Just for comparison, this can be mapped to **catch** in other languages, but not exactly same.

**recover** is a function which returns why the panic is created if there is one or returns **nil** if no panic is there. We have to handle the situation depending on the return value of **return** function.

### Program to illustrate how not to use recover

The motive of this program is to show how beginners may use recover in a wrong way. The recover in this program is totally  useless.

```go
package main

import "fmt"

func main() {
	fmt.Println("This line prints fine since it is before panic")
	panic("You thought recover under me can help you? Hahaha!!")
	a := recover()
	if a != nil {
		fmt.Println("After recovery")
	}
}
```
**Output**

![Output6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7qa9kxkh3xqebhyu57pg.png)

Since, the nothing after panic can run and execution stops there, recover is useless in the above case.

### Program to illustrate correct usage of recover

Okay fine, if we can't use recover after panic, there is only chance to use it before panic. But before panic, recover returns **nil** since there is won't be any panic at that time which is also of no use. Then how do we actually handle panic? This is where **defer** comes in handy.

Write the recover and other panic handling code inside a function and call the function before panic line with defer keyword. So, technically it is before panic, so executes and also executes after panic so that **recover** does not return **nil**

```go
package main

import "fmt"

func catch() {
	a := recover()
	if a != nil {
		fmt.Println("There is a panic, no worries, we handled it.")
	}
}

func panicking() {
	defer catch()
	panic("I am afraid, I might get caught!")
}

func random() {
	fmt.Println("Just there to show that program still continues")
}

func main() {
	panicking()
	random()
}

```
**Output**:

![Output7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/muojmfvakrea68c4lglo.png)

## Conclusion

I hope you liked it. Next part will be on **interfaces** in go.

Do follow me to see them. Make sure you like and share if you felt this good.

Let's connect on: [Twitter](https://twitter.com/VChiranjeeviAK) [LinkedIn](https://www.linkedin.com/in/chiranjeevi-tirunagari/) [Showwcase](https://www.showwcase.com/vchiranjeeviak)