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!!
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
沒有留言:
張貼留言