一文帶你掌握Golang中panic與recover的使用方法
panic
panic作用是終止當前正在運行的程序(包括所有協(xié)程)并輸出導(dǎo)致異常的堆棧信息。在遇到無法處理的異常情況時,例如比如數(shù)組越界、操作未初始化的map、空指針等都會觸發(fā)panic。主動觸發(fā)panic示例:
package main
func main() {
// 未處理的自定義異常
customException := "an error occurred"
panic(customException)
}
會輸出如下信息:
panic: an error occurred
goroutine 1 [running]:
main.main()
/Users/ning/projects/go/workspace/hello/panic/main.go:7 +0x34
Process finished with the exit code 2
數(shù)據(jù)越界導(dǎo)致panic示例:
package main
import "fmt"
func main() {
a := [2]int{4, 5}
fmt.Println(a[3])
}
會輸出如下信息:
# command-line-arguments
./main.go:11:16: invalid argument: array index 3 out of bounds [0:2]
Compilation finished with exit code 2
recover
recover可以讓觸發(fā)了panic的程序繼續(xù)運行,recover僅在延遲函數(shù)defer中有效,在正常的執(zhí)行過程中,調(diào)用recover會返回nil并且不產(chǎn)生其他任何效果。如果當前的goroutine觸發(fā)了panic,調(diào)用recover可以捕獲到panic的輸入值,并且恢復(fù)正常運行。這個特性對于像web服務(wù)就非常有用了, 當web服務(wù)處理某個請求時,某個方法觸發(fā)了panic,這時候顯然是不應(yīng)該直接讓web服務(wù)掛掉的。這種場景下,就可以使用recover來捕獲panic并且讓服務(wù)正常運行下去。
在其他語言里,通常是底層拋出異常,上層邏輯通過try/catch捕獲異常。defer/panic/recover配合使用可以實現(xiàn)類似try/catch的功能。
將Recover()寫在defer中,在可能發(fā)生panic的代碼之前執(zhí)行defer,當程序觸發(fā)panic后,系統(tǒng)將跳過后面的代碼,按照逆序執(zhí)行已經(jīng)注冊的defer函數(shù),如果defer函數(shù)中調(diào)用了recover(),recover()會返回捕獲到的panic的錯誤信息。
使用recover需要注意幾點:
- recover需要在defer的方法里面直接調(diào)用,不能對recover()包一層方法后再在defer的方法里面調(diào)用
- recover只能捕獲同一個協(xié)程中的panic,無法捕獲其它協(xié)程的panic
defer/panic/recover示例
成功捕獲實例一
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("recover:%v\n", err)
}
}()
panic("an error occurred")
}成功捕獲實例二
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("recover:%v\n", err)
}
}()
test()
}
func test() {
panic("an error occurred")
}
成功捕獲實例三
func main() {
test()
}
func test() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("recover:%v\n", err)
}
}()
panic("an error occurred")
}
不能捕獲實例一
func main() {
if err := recover(); err != nil {
fmt.Printf("recover:%v\n", err)
}
panic("an error occurred")
}
不能捕獲實例二
func main() {
go func() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("recover:%v\n", err)
}
}()
}()
panic("an error occurred")
}
不能捕獲實例三
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("recover:%v\n", err)
}
}()
go test()
for {
select {}
}
}
func test() {
panic("an error occurred")
}
不能捕獲實例四
func main() {
defer func() {
recoverFromPanic()
}()
test()
}
func recoverFromPanic() {
if err := recover(); err != nil {
fmt.Printf("recover:%v\n", err)
}
}
func test() {
panic("an error occurred")
}
不能捕獲實例五
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("recover:%v\n", err)
}
}()
test()
for {
select {}
}
}
func test() {
go func() {
panic("an error occurred")
}()
}以上就是一文帶你掌握Golang中panic與recover的使用方法的詳細內(nèi)容,更多關(guān)于Golang panic recover的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang語言中的Prometheus的日志模塊使用案例代碼編寫
這篇文章主要介紹了Golang語言中的Prometheus的日志模塊使用案例,本文給大家分享源代碼編寫方法,感興趣的朋友跟隨小編一起看看吧2024-08-08
詳解golang避免循環(huán)import問題(“import cycle not allowed”)
這篇文章主要給大家介紹了關(guān)于golang中不允許循環(huán)import問題("import cycle not allowed")的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習學(xué)習吧2018-08-08
使用Golang快速構(gòu)建出命令行應(yīng)用程序
在日常開發(fā)中,大家對命令行工具(CLI)想必特別熟悉了,如果說你不知道命令工具,那你可能是個假開發(fā)。每天都會使用大量的命令行工具,例如最常用的Git、Go、Docker等,這篇文章主要介紹了使用Golang快速構(gòu)建出命令行應(yīng)用程序,需要的朋友可以參考下2023-02-02
Golang實現(xiàn)異步上傳文件支持進度條查詢的方法
這篇文章主要介紹了Golang實現(xiàn)異步上傳文件支持進度條查詢的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧2019-10-10

