Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recover and continue for loop if panic occur Golang

Tags:

for-loop

go

panic

so my case is quite complex but for asking question in clean and clear context I am using simple for loop that initiate from 0 and goes upto 10. Now what I am trying to do is when i becomes equal to 2 program will consider this as panic. It will go to recover state using defer and then after recovery loop will resume.

So desired output should be something like that:

0
1
panic occured: got 2
3
4
.
.
.
.
.
10

Actual output I am getting

0
1
panic occured got:  got 2

Code block:

package main

import "fmt"

func main() {
    goFrom1To10()
}

func goFrom1To10() {
    defer recovery()
    for i := 0; i <= 10; i++ {

        if i == 2 {
            panic("got 2")

        }
        fmt.Println(i)
    }

}

func recovery() {
    if r := recover(); r != nil {
        fmt.Println("panic occured: ", r)
    }

}

Can this be achievable in go like when panic occur somehow we can recover and complete our loop?

like image 804
Ahsan Naseem Avatar asked Jun 30 '18 08:06

Ahsan Naseem


People also ask

How do you avoid panic in Golang?

“Panics are a major source of cascading failures,” the Uber Go Style Guide says. “If an error occurs, the function must return an error and allow the caller to decide how to handle it.” For that reason, instead of using panic() there, we can instead utilize t. Fatal and/or t.

What is panic and recover in Golang?

In Go, we use defer, panic and recover statements to handle errors. We use defer to delay the execution of functions that might cause an error. The panic statement terminates the program immediately and recover is used to recover the message during panic.

Does defer run on panic Golang?

defer won't work after panic because the control never reached the statement, hence it was never registered. This is like printing something after a return statement in a function, it's basically an unreachable code.

How do you capture panic in Golang?

Recover is a function provided by Go which takes control of a panicking goroutine. recover() can only be used inside deferred functions. If you call recover() during normal flow, it will simply return nil . However, if a goroutine is panicking, recover() will capture the panic value.


1 Answers

You can do that if the body of the loop is executed as a function, either anonymous or a named one, and in that function you use a deferred function to recover.

Here's how it looks like with anonymous functions:

func goFrom1To10() {
    for i := 0; i <= 10; i++ {
        func() {
            defer func() {
                if r := recover(); r != nil {
                    fmt.Println("panic occured: ", r)
                }
            }()

            if i == 2 {
                panic("got 2")
            }
            fmt.Println(i)
        }()
    }
}

Output (try it on the Go Playground):

0
1
panic occured:  got 2
3
4
5
6
7
8
9
10

It's nicer and easier to understand if you move it to a named function:

func goFrom1To10() {
    for i := 0; i <= 10; i++ {
        task(i)
    }
}

func task(i int) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("panic occured: ", r)
        }
    }()

    if i == 2 {
        panic("got 2")
    }
    fmt.Println(i)
}

Output is the same. Try this one on the Go Playground.

like image 56
icza Avatar answered Sep 24 '22 11:09

icza