如果发生 panic,如何恢复并继续循环 Golang。

10

我的情况相当复杂,但为了在干净、清晰的上下文中提问,我使用简单的for循环,从0开始到10。现在我想做的是当 i变成2 时,程序将视其为紧急情况。它会使用defer进入恢复状态,然后在恢复后继续循环。

所以期望的输出应该是这样的:

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

我得到的实际输出结果

0
1
panic occured got:  got 2

代码块:

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)
    }

}

在Go语言中,当出现恐慌的情况时,我们是否可以进行恢复并完成我们的循环?

1个回答

22

如果循环的主体作为函数执行,无论是匿名还是具名函数,并且在该函数中使用延迟函数进行恢复,那么您可以这样做。

以下是使用匿名函数的示例:

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)
        }()
    }
}

输出结果(在Go Playground上尝试):

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

如果你将其移至一个命名函数中,那么它会更易于理解和使用:

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)
}

输出结果相同。在Go Playground上试一试。


感谢@icza的回答和解释,您的逻辑和解决方案帮助我在这种情况下创建了单独的恐慌和恢复函数。再次感谢! - Ahsan Naseem
@icza,我无法理解其中的逻辑。请问您能否解释一下,为什么将恢复调用移到 panic 附近会发生这种情况? - Siyaram Malav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接