Welcome To Golang By Example

Recover panic from goroutine in Go (Golang)

Overview

There are two cases for recovering from a panic in a goroutine

While in the first case it will recover from panic. But an important point to note about recover function is that it can only recover the panic happening in the same goroutine.  If the panic is happening in a different goroutine and recover is in a different goroutine then it.

Let’s see an example for both

Recover function in the same goroutine as panic

package main

import "fmt"

func main() {
    a := []string{"a", "b"}
    go checkAndPrintWithRecover(a, 2)
    fmt.Println("Exiting normally")
}

func checkAndPrintWithRecover(a []string, index int) {
    defer handleOutOfBounds()
    checkAndPrint(a, 2)
}

func checkAndPrint(a []string, index int) {
    if index > (len(a) - 1) {
        panic("Out of bound access for slice")
    }
    fmt.Println(a[index])
}

func handleOutOfBounds() {
    if r := recover(); r != nil {
        fmt.Println("Recovering from panic:", r)
    }
}

Output

Exiting normally
Recovering from panic: Out of bound access for slice

In the above program recover and panic lie in the same goroutine hence it is able to recover from panic as seen from the output.

Recover function in a different goroutine as panic

As mentioned in this case it is not possible to recover from panic.

package main
import "fmt"
func main() {
    a := []string{"a", "b"}
    checkAndPrintWithRecover(a, 2)
    fmt.Println("Exiting normally")
}
func checkAndPrintWithRecover(a []string, index int) {
    defer handleOutOfBounds()
    go checkAndPrint(a, 2)
}
func checkAndPrint(a []string, index int) {
    if index > (len(a) - 1) {
        panic("Out of bound access for slice")
    }
    fmt.Println(a[index])
}
func handleOutOfBounds() {
    if r := recover(); r != nil {
        fmt.Println("Recovering from panic:", r)
    }
}

Output

Exiting normally
panic: Out of bound access for slice

goroutine 18 [running]:
main.checkAndPrint(0xc0000a6020, 0x2, 0x2, 0x2)
        /Users/slohia/go/src/github.com/golang-examples/articles/tutorial/panicRecover/goroutine/main.go:19 +0xe2
created by main.checkAndPrintWithRecover
        /Users/slohia/go/src/github.com/golang-examples/articles/tutorial/panicRecover/goroutine/main.go:14 +0x82
exit status 2

In the above program we have checkAndPrint in the goroutine and it raises panic in that goroutine.  The recover function is in the calling goroutine. As you can see from the output that it does not stop panic and hence you see the a