網頁

2023/3/6

Golang for迴圈中的recover panic無法繼續執行?

Go程式在for迴圈中panic時仍可繼續執行的作法如下。


例如下面for迴圈中發生panic時程式即結束,迴圈剩下的部分未繼續執行。

main.go

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 5; i++ {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("recovered", r)
            }
        }()
        if i == 2 {
            panic("panic!")
        }
        fmt.Println(i)
    }
}

執行結果如下,執行到i == 2時發生panic就停止了。

0
1
recovered panic!

這是因為panic會中斷當前的goroutine並離開函式,recover()只是捕捉panic,recover執行完仍會離開函式。而上面從頭到尾都只在一個goroutine的main()函式中執行,所以main()中發生panic時會先執行defer函式的recover後然後離開main()

若要讓for迴圈中發生panic時仍能繼續執行,可用一個函式包裝panic及recover。例如下面用一個匿名函式包裝原本的panic及recover,則panic發生時是跳離所包裝的匿名函式而非main()函式,跳離後再下一次迴圈又開始了新的匿名函式來執行。

main.go

package main
package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 5; i++ {
        func() {
            defer func() {
                if r := recover(); r != nil {
                    fmt.Println("recovered", r)
                }
            }()
            if i == 2 {
                panic("panic!")
            }
            fmt.Println(i)
        }()
    }
}

執行印出如下,panic及recover後迴圈仍繼續進行。

0
1
recovered panic!
3
4


沒有留言:

張貼留言