1. 程式人生 > >Golang 中的 panic 與 recover 理解

Golang 中的 panic 與 recover 理解

Golang 有2個內建的函式 panic() 和 recover(),用以報告和捕獲執行時發生的程式錯誤,與 error 不同,panic-recover 一般用在函式內部。一定要注意不要濫用 panic-recover,可能會導致效能問題。

使用panic丟擲異常,丟擲異常後將立即停止當前函式的執行並執行所有被defer的函式,然後將panic拋向上一層,直至程式carsh。但是也可以使用被defer的recover函式來捕獲異常阻止程式的崩潰,recover只有被defer後才是有意義的。

必須注意:
1. defer 需要放在 panic 之前定義,另外recover只有在 defer 呼叫的函式中才有效。
2. recover處理異常後,邏輯並不會恢復到 panic 那個點去,函式跑到 defer 之後的那個點.
3. 多個 defer 會形成 defer 棧,後定義的 defer 語句會被最先呼叫

panic (主動爆出異常) 與 recover (收集異常)

recover 用來對panic的異常進行捕獲. panic 用於向上傳遞異常,執行順序是在 defer 之後。

下面舉個含有異常的例子:

func f() {
    for {
        fmt.Println("1")
        a := []string{"a","b"}
        fmt.Println(a[3])  // 這裡slice越界異常了
        /*panic("bug")*/
        fmt.Println("4")
        time.Sleep(1 * time
.Second) } }

如果不把這個異常panic recover處理的化,那麼就會發生下面的情況.

1
panic: runtime error: index out of range

goroutine 1 [running]:
panic(0xda9c0, 0x8201c8090)
    /usr/local/go/src/runtime/panic.go:464 +0x3e6
main.f()
    /Users/dxy/gg.go:23 +0x33b
main.main()
    /Users/dxy/gg.go:16 +0x14
exit status 2

下面是處理panic的例子.

import
( "fmt" "time" ) func main() { defer func() { //必須要先宣告defer,否則不能捕獲到panic異常 fmt.Println("2") if err := recover(); err != nil { fmt.Println(err) //這裡的err其實就是panic傳入的內容,bug } fmt.Println("3") }() f() } func f() { for { fmt.Println("1") panic("bug") fmt.Println("4") //不會執行的. time.Sleep(1 * time.Second) } }

那麼上面程式碼的執行結果是:

1
2
bug
3

上面go程式碼例項中,異常是我們通過panic方法主動丟擲來的,但如果真的就出現了未知的異常咋辦?

package main

import (
    "fmt"
    "time"
)

func main() {
    f()
    fmt.Println("end")
}

func f() {
    defer func() { //必須要先宣告defer,否則不能捕獲到panic異常
        fmt.Println("netdxy.cn start")
        if err := recover(); err != nil {
            fmt.Println(err) //這裡的err其實就是panic傳入的內容,"bug"
        }
        fmt.Println("netdxy.cn end")
    }()
    for {
        fmt.Println("1")
        a := []string{"a", "b"}
        fmt.Println(a[3])  // 越界訪問,肯定出現異常
        panic("bug”)  // 上面已經出現異常了,所以肯定走不到這裡了。 
        fmt.Println("4") //不會執行的.
        time.Sleep(1 * time.Second)
    }
}

我們可以看到出現的異常會走到defer這一步,defer這裡可以列印具體的異常資訊,defer執行完之後不能回到原點,控制權會被扔到該函式的外層,也就是呼叫這個函式的層,對應上面的程式碼也就是main()函式。
上面go程式碼執行結果是:

1
netdxy.cn start
runtime error: index out of range
netdxy.cn end
end 

相關推薦

Golang panic recover 理解

Golang 有2個內建的函式 panic() 和 recover(),用以報告和捕獲執行時發生的程式錯誤,與 error 不同,panic-recover 一般用在函式內部。一定要注意不要濫用 panic-recover,可能會導致效能問題。 使用panic

GO_05_2:Golang panicrecover、defer 的用法

log logs lan finall 可能 錯誤處理 錯誤 異常處理 auto 函數 defer   1. 它的執行方式類似其他語言中的折構函數,在函數體執行結束後按照調用順序的 相反順序 逐個執行   2. 即使函數發生 嚴重錯誤 也會被執行,類似於 java 中 t

GolangStructDB表字段通過反射自動映射 - sqlmapper

size http 維護 default arc struct 自動 地址 字符 Golang中操作數據庫已經有現成的庫"database/sql"可以用,但是"database/sql"只提供了最基礎的操作接口; 對數據庫中一張表的增刪改查等操作,必須手動編寫sql st

mybatis的${}#{}的理解

破壞 字段名 數據 from 兩種 opera 使用場景 any operator   mybatis作為目前java較為常使用的orm框架,其中動態sql的參數的註入有${}與#{兩種形式,下面來介紹一下他們之間的區別,   #{}作為參數註入的方式時,從表象上來看,是在

Golangmakenew

轉自:https://www.cnblogs.com/junneyang/p/6070238.html   make、new操作 make用於內建型別(map、slice 和channel)的記憶體分配。new用於各種型別的記憶體分配。 內建函式new本質上說跟其

golangjsonstructtag

使用 Golang 的 encoding/json 庫已經提供了很好的封裝,可以讓我們很方便地進行 JSON 資料的轉換。 Go 語言中資料結構和 JSON 型別的對應關係如下表: golang 型別 JSON 型別 注意事項 bool JSO

go panicrecover分析及錯誤處理

先介紹一下什麼叫error 型別 error 是一種型別,表示錯誤狀態的型別,如果沒有錯誤則是nil。直白點將:error 型別就是描述錯誤的一種型別。 panic 在golang goroutine 的作用 panic 官方文件介紹:

golangjsonstructtag簡介

使用 Golang 的 encoding/json 庫已經提供了很好的封裝,可以讓我們很方便地進行 JSON 資料的轉換。 Go 語言中資料結構和 JSON 型別的對應關係如下表: golang 型別 JSON 型別 注意事項 bool JSON boolean

Golang位運算的理解於應用場景

pan golang ike xor 需要 常用 一個 amp 符號 一:位運算的介紹 百度百科的介紹,大家作為一個參考說明 https://baike.baidu.com/item/%E4%BD%8D%E8%BF%90%E7%AE%97/6888804?fr=al

golangArraySlice

range make imp 形參 隱式 amp [] 報錯 同時 在golang中有數組和Slice兩種數據結構,Slice是基於數組的實現,是長度動態不固定的數據結構,本質上是一個對數組字序列的引用,提供了對數組的輕量級訪問。那麽在go的函數中以數組或Slice為形參的

Golangpanicrecover

func panic(interface{})和func recover() interface{}是Golang中用於錯誤處理的兩個函式。 panic的作用就是丟擲一條錯誤資訊,從它的引數型別可以看到它可以丟擲任意型別的錯誤資訊。在函式執行過程中的某處呼叫了panic,則立即丟擲一個錯誤資訊,同時

golangrecoverpanic用法

golang中沒有try... catch...,所以當golang中遇到panic時,如果不進行recover,便會導致整個程式掛掉,具體例子如下: package main import ( "fmt" ) func main() { panic("fault

99%的人都理解錯了HTTPGETPOST的區別

tex method 無限 ext 一點 size 環境 ans 交通 GET和POST是HTTP請求的兩種基本方法,要說它們的區別,接觸過WEB開發的人都能說出一二。 最直觀的區別就是GET把參數包含在URL中,POST通過request body傳遞參數。

【轉】C#FuncAction的理解

.net ring UNC 簡單 代碼 操作 不必要 返回值 tps 原文地址:https://www.cnblogs.com/ultimateWorld/p/5608122.html Action 與 Func是.NET類庫中增加的內置委托,以便更加簡潔方便的使用委托。最

JavaScript在頁面的執行順序(理解聲明式函數賦值式函數) 轉載

AD TE 我們 行動 first FN 順序 而且 編譯性語言 JavaScript在頁面中的執行順序 https://blog.csdn.net/superhoy/article/details/52946277 2016年10月27日 15:38:52 閱讀數:

自己對golang各個文件的理解

mode bsp 關於 信息 outer model option 其他 都是 models -》 裏面寫關於數據庫方面數據controllers -》邏輯,請求方法等conf -》註冊數據庫信息routers -》初始化路由線路views -》測試界面 實際

Yii2.0Yii::$appYii 1.0Yii:app()的理解

框架源碼 靜態 UNC 一個 eap eba 你在 this 模式 一直不明白Yii::$app與Yii::app(),查找yii框架源碼後如下記錄分享 (1)在Yii1.0中Yii::app()返回的是你在index.php裏創建的CWebApplication實例,在對

99%的人可能都理解錯了HTTPGETPOST的區別

角色 ref 裏的 們的 接受 遺憾 為什麽 eth ges GET和POST是HTTP請求的兩種基本方法,要說它們的區別,接觸過WEB開發的人都能說出一二。 最直觀的區別就是GET把參數包含在URL中,POST通過request body傳遞參數。 你可能自己寫過無數個G

Golang 如何用 CGO C 之間做一個快取 buffer

Golang 是一個不錯的語言,尤其是做一個快取中間層是非常非常容易的。比較常見的場景就是我們在讀一個很大很大的檔案的時候,我們是做不到一次載入檔案到記憶體的,Golang 可以做到一點一點的將檔案讀至末尾,慢慢處理完,相信很多語言也很容易做到這個,那如果在處理這個檔案的時候專案的主語言是 Golang 而需