golang

Golang Recover

The Golang recover function is used to recover a goroutine from a panic. Think of it like a try/catch block in other programming languages. We can use the recover method to recover the program from an error raised by a panic method. This helps us to gracefully handle errors in case of errors rather than terminating the program.

Let us explore how we can use the recover method to recover a program from a panic.

Golang Recover Method

The recover method is a built-in method that is defined in the Go built-in package. The function syntax is as shown:

func recover() interface{}

To implement the recover function appropriately, the following conditions must be met:

  1. Always call the recover function inside a deferred function. This is because deferred methods to do not terminate in the case of a panic. This makes them able to recover the program once a panic occurs. Check our tutorial on Golang Panic to learn more.
  2. The recover method os only applicable in a goroutine that encounters a panic. If called in a goroutine that does not experience the panic, the recover does not work.

Example 1

The example below illustrates how to use the recover method.

package main
import "fmt"
func panic_me() {
    panic("Wasted!")
}
func main() {
    defer func() {
        if rec := recover(); rec != nil {
            fmt.Println("Whew!, I am saved")
        }
    }()
    panic_me()
    fmt.Println("I can't run")
}

In the example above, we create a function that panics. Inside the main function, we create a defer function that tries to recover the program. If the recovery is success, it prints a message inside the if block.

If we run the program above, we should get an output as shown:

$ go run recover.go
Whew!, I am saved

Note that the message inside the main block does not execute. This is because the main function is destroyed immediately after the panic. Only the deferred method can run after a panic.

Example 2

The example below also illustrates how to recover a program from an out of bound index.

package main
import (
    "fmt"
    "runtime/debug"
)
func dontPanic() {
    if rec := recover(); rec != nil {
        fmt.Println("I nearly died")
    }
    debug.PrintStack()
}
func getValue(slice []int, index int) {
    if index > (len(slice) - 1) {
        panic("Illegal index access!")
    }
    fmt.Println(slice[index])
}
func main() {
    slc := []int{1, 2, 3}
    defer dontPanic()
    getValue(slc, 5)
}

In the example above, we create a function that handles the panic using the recover method and prints the stack trace using the debug.PrintStack() method.

Now, if try to access an element with an out of bound index, the recover method handles the panic.

The code above should return an error as:

I nearly died
goroutine 1 [running]:
runtime/debug.Stack()
        C:/Program Files/Go/src/runtime/debug/stack.go:24 +0x65
runtime/debug.PrintStack()
        C:/Program Files/Go/src/runtime/debug/stack.go:16 +0x19
main.dontPanic()
        recover.go:15 +0x6a
panic({0xa54b20, 0xa861b8})
        C:/Program Files/Go/src/runtime/panic.go:1038 +0x215
main.getValue({0xc0000cdf50, 0xc0000cdf70, 0x9c52b9}, 0x60)
        recover.go:19 +0x98
main.main()
        recover.go:33 +0x7e

The above represent the stack trace as the program panics.

Conclusion

In this article, we cover how to recover a program from a panic using the recover method. We also learnt how to get the stack trace if a program panics using the debug.Panic() method.

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list