網頁

2022/5/19

Golang panic recover簡介

Go的panic與reocver簡介。


範例環境:

  • Go 1.18


Panic

Go調用內建函式panic()會中斷當前的goroutine並離開函式,而函式中panic前的defer會先執行。

例如下面執行時在doPanic()中發出panic中斷程式。

main.go

package main

import "fmt"

func main() {
    doPanic()
    fmt.Println("hello world")
}

func doPanic() {
    fmt.Println("before panic")
    defer fmt.Println("defer after panic")

    panic("panic!!")
}

執行結果如下。可以看到defer的"defer after panic"先印出後才panic,而panic後的"hello world"沒被印出。

before panic
defer after panic
panic: panic!!

goroutine 1 [running]:
main.doPanic()
        /../main.go:14 +0xb5
main.main()
        /../main.go:6 +0x19
exit status 2


Recover

Go的內建函式recover()回復被panic中斷的程序並取得panic()時傳入的值。注意recover()必須在defer函式中才有效果,因為只有defer函式會在panic中斷前執行。

例如下面在doPanic()之前加上defer函式並在內呼叫recover()復原panic的中斷。

main.go

package main

import "fmt"

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recovered", r)
        }
    }()
    doPanic()
    fmt.Println("hello world")
}

func doPanic() {
    fmt.Println("before panic")
    defer fmt.Println("defer after panic")

    panic("panic!!")
}

執行結果如下,可以看到defer函式中recover的效果。不過panic後的程序依舊不會執行。

before panic
defer after panic
recovered panic!!

github


Goroutine panic

Panic只會中斷當下的goroutine而不會影響其他goroutine的執行。例如下面改用另一goroutine執行doPanic(),則不影響main原有goroutine的執行。

main.go

package main

import (
    "fmt"
    "time"
)

func main() {
    go doPanic()
    fmt.Println("hello world")
    time.Sleep(time.Second * 1)
}

func doPanic() {
    fmt.Println("before panic")
    defer fmt.Println("defer after panic")

    panic("panic!!")
}

執行結果如下,可以看到main goroutine的"hello world"有印出不被go doPanic()影響。

hello world
before panic
defer after panic
panic: panic!!

goroutine 6 [running]:
main.doPanic()
        /../main.go:18 +0xb5
created by main.main
        /../main.go:9 +0x25
exit status 2


沒有留言:

張貼留言