一文詳細(xì)談?wù)凣oLang的panic和error
前言
首先說一下: 錯誤指的是可能出現(xiàn)問題的地方出現(xiàn)了問題。如打開件失敗,這種情況在意料之中 。異常指的是不應(yīng)該出現(xiàn)問題的地方出現(xiàn)了問題。如引用了空指針,這種情況在意料之外
Go
提供兩種錯誤處理方式
- 函數(shù)返回
error
類型對象判斷錯誤 panic
異常
1. panic
Go的類型系統(tǒng)會在編譯時捕獲很多錯誤,但有些錯誤只能在運行時檢查,如數(shù)組訪問越界、空指針引用等。這些運行時錯誤會引起painc異常。
一般而言,當(dāng)panic異常發(fā)生時,程序會中斷運行,并立即執(zhí)行在該goroutine(可以先理解成線程)中被延遲的函數(shù)(defer 機制)。隨后,程序崩潰并輸出日志信息。日志信息包括panic value和函數(shù)調(diào)用的堆棧跟蹤信息。panic value通常是某種錯誤信息。對于每個goroutine,日志信息中都會有與之相對的,發(fā)生panic時的函數(shù)調(diào)用堆棧跟蹤信息。通常,我們不需要再次運行程序去定位問題,日志信息已經(jīng)提供了足夠的診斷依據(jù)。因此,在我們填寫問題報告時,一般會將panic異常和日志信息一并記錄。不是所有的panic異常都來自運行時,直接調(diào)用內(nèi)置的panic函數(shù)也會引發(fā)panic異常;panic函數(shù)接受任何值作為參數(shù)。當(dāng)某些不應(yīng)該發(fā)生的場景發(fā)生時,我們就應(yīng)該調(diào)用panic。雖然Go的panic機制類似于其他語言的異常,但panic的適用場景有一些不同。由于panic會引起程序的崩潰,因此panic一般用于嚴(yán)重錯誤,如程序內(nèi)部的邏輯不一致。
panic
可以手工調(diào)用,但是 Go
官方建議盡量不要使用panic
,每一個異常都應(yīng)該用 error
對象捕獲。如果異常出現(xiàn)了,但沒有被捕獲并恢復(fù),Go
程序的執(zhí)行就會被終止,即便出現(xiàn)異常的位置不在主 Goroutine
中也會這樣。
總結(jié)來說:
panic是一個嚴(yán)重錯誤機制,它會導(dǎo)致程序終止,并依次逆序執(zhí)行 panic 所在函數(shù)可能存在的 defer 函數(shù)列表,然后返回該函數(shù)的調(diào)用方。recover 內(nèi)置函數(shù)可用于捕獲 panic,重新恢復(fù)程序正常執(zhí)行流程,但是 recover 函數(shù)只有在 defer 內(nèi)部使用才有效
此外,當(dāng) panic()
觸發(fā)的宕機發(fā)生時, panic()
后面的代碼將不會被運行,但是在 panic()
函數(shù)前面已經(jīng)運行過的 defer
語句依然會在宕機發(fā)生時發(fā)生作用
2. recover
1. recover
是一個 Go
語言的內(nèi)建函數(shù),可以讓進入宕機流程中的 goroutine
恢復(fù)過來。
2. 用來控制一個goroutine的panicking行為,捕獲panic,從而影響應(yīng)用的行為
3. 一般的調(diào)用建議
a). 在defer函數(shù)中,通過recever來終止一個gojroutine的panicking過程,從而恢復(fù)正常代碼的執(zhí)行
b). 可以獲取通過panic傳遞的error
簡單來講:go中可以拋出一個panic的異常,然后在defer中通過recover捕獲這個異常,然后正常處理。
4. 在正常的執(zhí)行過程中,調(diào)用 recover
會返回 nil
并且沒有其他任何效果;
注意:利用recover處理panic指令,defer必須在panic之前聲明,否則當(dāng)panic時,recover無法捕獲到panic.
總結(jié)來說 Go
語言沒有異常系統(tǒng),其使用 panic
觸發(fā)宕機類似于其他語言的拋出異常, recover
的宕機恢復(fù)機制就對應(yīng)其它語言中的 try/catch
機制。
panic 和 recover 的關(guān)系
panic 和 recover 的組合有如下特性:
有 panic 沒 recover ,程序宕機。
有 panic 也有 recover ,程序不會宕機,執(zhí)行完對應(yīng)的 defer 后,從宕機點退出當(dāng)前函數(shù)后繼續(xù)執(zhí)行。
注意:在 panic 觸發(fā)的 defer 函數(shù)內(nèi),可以繼續(xù)調(diào)用 panic ,進一步將錯誤外拋,直到程序整體崩潰。如果想在捕獲錯誤時設(shè)置當(dāng)前函數(shù)的返回值,可以對返回值使用命名返回值方式直接進行設(shè)置。
示例:
package main func test() { defer func() { if err := recover(); err != nil { // recover 捕獲錯誤。 println(err.(string)) // 將 interface{} 轉(zhuǎn)型為具體類型。 } }() panic("panic error!") // panic 拋出錯誤 } func main() { test() }
3. error
go中的錯誤處理,是通過返回值的形式來出來,要么你忽略,要么你處理(處理也可以是繼續(xù)返回給調(diào)用者),對于golang這種設(shè)計方式,我們會在代碼中寫大量的if判斷,以便做出決定。
對于err如果是nil就代表沒有錯誤,如果不是nil就代表程序出問題了,需要對錯誤進行處理了。
示例:
func main() { conent,err:=ioutil.ReadFile("filepath") if err !=nil{ //錯誤處理 }else { fmt.Println(string(conent)) } }
此外,error類型是go語言的一種內(nèi)置類型,使用的時候不用特定去import,他本質(zhì)上是一個接口,
type error interface{ Error() string //Error()是每一個訂制的error對象需要填充的錯誤消息,可以理解成是一個字段Error }
總結(jié)
到此這篇關(guān)于GoLang中panic和error的文章就介紹到這了,更多相關(guān)GoLang的panic和error內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
GoLang中生成UUID唯一標(biāo)識的實現(xiàn)
這篇文章主要介紹了GoLang中生成UUID唯一標(biāo)識的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05Bililive-go 實現(xiàn)直播自動監(jiān)控錄制功能
最近有直播錄制的需求,但是自己手動錄制太麻煩繁瑣,于是用了開源項目Bililive-go進行全自動監(jiān)控錄制,對Bililive-go 直播自動監(jiān)控錄制實現(xiàn)思路感興趣的朋友,一起看看吧2024-03-03golang hack插件開發(fā)動態(tài)鏈接庫實例探究
這篇文章主要為大家介紹了golang hack插件開發(fā)動態(tài)鏈接庫實例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01