Go高級(jí)特性探究之recover捕獲panic詳解
在Go語(yǔ)言中,當(dāng)程序出現(xiàn)panic(即運(yùn)行時(shí)錯(cuò)誤)時(shí),程序會(huì)立即停止當(dāng)前的執(zhí)行流程,并在函數(shù)調(diào)用堆棧向上逐層返回,直到遇到recover函數(shù)或程序終止為止。
而recover函數(shù)的作用就是捕獲這個(gè)panic,并恢復(fù)正常的執(zhí)行流程。在Gin框架中,提供了recover中間件來(lái)自動(dòng)捕獲panic,并轉(zhuǎn)換為HTTP 500錯(cuò)誤返回給客戶端。
使用
使用recover中間件非常簡(jiǎn)單,只需要在Gin路由中添加即可:
router := gin.Default() router.Use(gin.Recovery())
需要注意的是,recover中間件應(yīng)該在Gin路由中的第一個(gè)聲明,以確保可以捕獲所有的panic。
配合日志打印與埋點(diǎn)上報(bào)
在API開發(fā)中,當(dāng)用戶請(qǐng)求接口時(shí),有時(shí)候會(huì)遇到一些問題,如訪問url錯(cuò)誤、參數(shù)錯(cuò)誤、數(shù)據(jù)庫(kù)連接超時(shí)等。雖然recover中間件可以避免由程序錯(cuò)誤導(dǎo)致的panic,但仍然需要記錄這些錯(cuò)誤信息來(lái)協(xié)助問題的排查和定位。
因此,我們可以配合日志打印和埋點(diǎn)上報(bào)來(lái)記錄這些錯(cuò)誤。以日志打印為例,Gin框架提供了官方的Logger中間件,可以使用Logger來(lái)記錄錯(cuò)誤信息:
router := gin.Default() // Logger 中間件將請(qǐng)求的URL、響應(yīng)時(shí)間、響應(yīng)狀態(tài)碼和請(qǐng)求的IP地址寫入日志文件 router.Use(gin.Logger()) // Recover 中間件將 panic 轉(zhuǎn)換為 500 錯(cuò)誤,并寫入日志文件 router.Use(gin.Recovery()) // 業(yè)務(wù)代碼 router.GET("/api", func(c \*gin.Context) { ? ? // code ? ? if err != nil { ? ? ? ? // 某個(gè)函數(shù)拋出了 panic ? ? ? ? log.Printf("\[ERROR] - %v\n", err) ? ? ? ? c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ ? ? ? ? ? ? "message": "內(nèi)部錯(cuò)誤,請(qǐng)稍后重試", ? ? ? ? }) ? ? ? ? return ? ? } ? ? // code })
在上述代碼中,我們使用log來(lái)記錄錯(cuò)誤信息,并在響應(yīng)中返回了錯(cuò)誤提示。這樣我們就能及時(shí)的發(fā)現(xiàn)問題并進(jìn)行排查了。
當(dāng)然,我們還可以在記錄錯(cuò)誤信息的同時(shí)上傳到埋點(diǎn)工具中,例如Sentry、Zipkin
等,來(lái)實(shí)現(xiàn)自動(dòng)的錯(cuò)誤上報(bào)和監(jiān)控。
recover在開源項(xiàng)目中的使用
recover中間件在開源項(xiàng)目中廣泛應(yīng)用,例如Prometheus、etcd、Kubernetes等項(xiàng)目中都有使用。
以etcd為例,它使用recover中間件捕獲所有的panic,并在日志中記錄錯(cuò)誤信息,如下所示:
func (s *EtcdServer) recoverAndLog(rctx rpctypes.Context, w http.ResponseWriter, req *http.Request) { ? ? data, err := ioutil.ReadAll(req.Body) ? ? if err != nil { ? ? ? ? writeError(w, rctx, err) ? ? ? ? return ? ? } ? ? defer func() { ? ? ? ? if v := recover(); v != nil { ? ? ? ? ? ? log.Printf("panic: %v", v) ? ? ? ? ? ? writeError(w, rctx, fmt.Errorf("panic: %v", v)) ? ? ? ? } ? ? }() ? ? // code }
在該函數(shù)中,使用了defer關(guān)鍵字調(diào)用recover函數(shù)捕獲panic,并使用log記錄錯(cuò)誤信息并返回錯(cuò)誤提示。
總結(jié)
通過Gin框架中的recover中間件,我們可以方便的捕獲和處理程序運(yùn)行時(shí)的錯(cuò)誤,從而提高了API服務(wù)的穩(wěn)定性和可靠性。同時(shí),配合日志打印和埋點(diǎn)上報(bào),可以更好地記錄錯(cuò)誤信息和輔助問題的排查和解決。在開源項(xiàng)目中,recover中間件也被廣泛應(yīng)用,并幫助了很多項(xiàng)目實(shí)現(xiàn)了穩(wěn)定的運(yùn)行。
到此這篇關(guān)于Go高級(jí)特性探究之recover捕獲panic詳解的文章就介紹到這了,更多相關(guān)Go recover捕獲panic內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go語(yǔ)言int64整型轉(zhuǎn)字符串的實(shí)現(xiàn)
本文主要介紹了go語(yǔ)言int64整型轉(zhuǎn)字符串的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03Golang 標(biāo)準(zhǔn)庫(kù) tips之waitgroup詳解
本篇文章給大家介紹Golang 標(biāo)準(zhǔn)庫(kù) tips之waitgroup的相關(guān)知識(shí),包括使用 channel 實(shí)現(xiàn) WaitGroup 的功能介紹,感興趣的朋友跟隨小編一起看看吧2021-07-07Go語(yǔ)言基礎(chǔ)go install命令使用示例詳解
這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)go install命令的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11Golang 函數(shù)執(zhí)行時(shí)間統(tǒng)計(jì)裝飾器的一個(gè)實(shí)現(xiàn)詳解
這篇文章主要介紹了Golang 函數(shù)執(zhí)行時(shí)間統(tǒng)計(jì)裝飾器的一個(gè)實(shí)現(xiàn)詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2019-03-03詳解Go語(yǔ)言如何利用高階函數(shù)寫出優(yōu)雅的代碼
高階函數(shù)(Hiher-order?Function)定義為:滿足下列條件之一的函數(shù):接收一個(gè)或多個(gè)函數(shù)作為參數(shù);返回值是一個(gè)函數(shù)。本文為大家介紹了如何利用高階函數(shù)寫出優(yōu)雅的代碼,希望對(duì)大家有所幫助2023-01-01Go|使用Options模式和建造者模式創(chuàng)建對(duì)象實(shí)戰(zhàn)
這篇文章主要介紹了Go使用Options模式和建造者模式創(chuàng)建對(duì)象實(shí)戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04