Go gin框架處理panic的方法詳解
本文我們介紹下recover在gin框架中的應(yīng)用。 首先,在golang中,如果在子協(xié)程中遇到了panic,那么主協(xié)程也會(huì)被終止。如下:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 在子協(xié)程中引起panic,主協(xié)程也會(huì)退出
go func() {
panic("hello world")
}()
// Listen and Server in 0.0.0.0:8080
r.Run(":8080")
}panic被描述為不可處理的錯(cuò)誤。在web服務(wù)中就是服務(wù)會(huì)崩潰。當(dāng)然,這在生產(chǎn)環(huán)境下是不可接受的。那么,如何能夠做到發(fā)生panic時(shí)技能捕獲該panic又能讓服務(wù)繼續(xù)健康運(yùn)行呢?
這就是golang中提供的recover函數(shù)了。recover函數(shù)能夠捕獲Panic錯(cuò)誤并恢復(fù)程序的正常運(yùn)行。
接下來(lái),我們看下recover函數(shù)在gin框架中是如何應(yīng)用的。
首先,要提到的就是gin框架中的recovery中間件。在gin中,是通過(guò)使用該中間件來(lái)捕獲panic,并保證服務(wù)不down機(jī)的。 如果使用gin.Default()函數(shù)進(jìn)行構(gòu)建gin對(duì)象,那么默認(rèn)就注冊(cè)了Recovery中間件。
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
// 注冊(cè)了Recovery中間件
engine.Use(Logger(), Recovery())
return engine
}其次,我們來(lái)看下Recovery()中間件都做了些什么。
Recovery()函數(shù)定義如下:
func Recovery() HandlerFunc {
return RecoveryWithWriter(DefaultErrorWriter)
}這里的DefaultErrorWriter是默認(rèn)的輸出端,即os.Stderr。即指錯(cuò)誤的輸出到什么地方。
接下來(lái)看RecoveryWithWriter函數(shù)中的實(shí)現(xiàn)
// RecoveryWithWriter returns a middleware for a given writer that recovers from any panics and writes a 500 if there was one.
func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) HandlerFunc {
if len(recovery) > 0 {
return CustomRecoveryWithWriter(out, recovery[0])
}
return CustomRecoveryWithWriter(out, defaultHandleRecovery)
}這里有一個(gè)參數(shù)是defaultHandleRecovery,我們看下它的實(shí)現(xiàn):
func defaultHandleRecovery(c *Context, err any) {
c.AbortWithStatus(http.StatusInternalServerError)
}就是寫(xiě)入了一個(gè)代表內(nèi)部服務(wù)器錯(cuò)誤的狀態(tài)碼500,并結(jié)束了本次請(qǐng)求。
這里關(guān)鍵點(diǎn)是CustomRecoveryWithWriter的實(shí)現(xiàn),代碼很長(zhǎng),我們分段來(lái)看。如下:

主要分三部分:
將日志輸出到out中,這里是上述提到的DefaultErrorWriter,即os.Stderr。
defer延遲執(zhí)行部分。
c.Next()正常請(qǐng)求處理器部分。
這里需要注意的點(diǎn)就是:
recover函數(shù)需要再defer中調(diào)用。因?yàn)閐efer是在函數(shù)返回時(shí)才調(diào)用,所以當(dāng)發(fā)生panic時(shí)會(huì)導(dǎo)致函數(shù)返回,這樣才能捕獲panic。
作為中間件運(yùn)行,說(shuō)明每次請(qǐng)求的處理器都被中間件包裝了,也就相當(dāng)于每個(gè)請(qǐng)求處理器都有這個(gè)defer函數(shù)。
在defer函數(shù)中,如果捕獲了panic,則將panic的詳細(xì)詳細(xì)記錄下來(lái),可以發(fā)送到指定的輸出中,即函數(shù)中指定的out參數(shù)(默認(rèn)是os.Stderr),也可以指定其他的文件或Sentry等。
在gin中,正是該中間件的應(yīng)用,確保了web服務(wù)的健壯性。當(dāng)然,其他的web框架也有同樣的機(jī)制,實(shí)現(xiàn)原理也是一樣的。
以上就是Go gin框架處理panic的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Go gin框架處理panic的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang小游戲開(kāi)發(fā)實(shí)戰(zhàn)之飛翔的小鳥(niǎo)
這篇文章主要給大家介紹了關(guān)于golang小游戲開(kāi)發(fā)實(shí)戰(zhàn)之飛翔的小鳥(niǎo)的相關(guān)資料,,本文可以帶你你從零開(kāi)始,一步一步的開(kāi)發(fā)出這款小游戲,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03
golang?四則運(yùn)算計(jì)算器yacc歸約手寫(xiě)實(shí)現(xiàn)
這篇文章主要為大家介紹了golang?四則運(yùn)算?計(jì)算器?yacc?歸約的手寫(xiě)實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
深入理解Go gin框架中Context的Request和Writer對(duì)象
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言的gin框架中Context的Request和Writer對(duì)象,文中的示例代碼講解詳細(xì),對(duì)我們深入了解Go語(yǔ)言有一定的幫助,快跟隨小編一起學(xué)習(xí)一下吧2023-04-04
Golang內(nèi)存模型教科書(shū)級(jí)講解
go官方介紹go內(nèi)存模型的時(shí)候說(shuō):探究在什么條件下,goroutine?在讀取一個(gè)變量的值的時(shí),能夠看到其它?goroutine?對(duì)這個(gè)變量進(jìn)行的寫(xiě)的結(jié)果,Go內(nèi)存模型規(guī)定了一些條件,在這些條件下,在一個(gè)goroutine中讀取變量返回的值能夠確保是另一個(gè)goroutine中對(duì)該變量寫(xiě)入的值2023-03-03
Golang實(shí)現(xiàn)AES加密和解密的示例代碼
AES( advanced encryption standard)使用相同密鑰進(jìn)行加密和解密,也就是對(duì)稱(chēng)加密。本文將詳細(xì)講解Golang實(shí)現(xiàn)AES加密和解密的方法,感興趣的可以學(xué)習(xí)一下2022-05-05
Go語(yǔ)言中reflect.DeepEqual函數(shù)的具體使用
本文主要介紹了Go語(yǔ)言中reflect.DeepEqual函數(shù)的具體使用,reflect.DeepEqual()函數(shù)是用來(lái)比較兩個(gè)值是否相等的方法,下面就來(lái)介紹一下,感興趣的可以了解一下2024-08-08
go?micro微服務(wù)proto開(kāi)發(fā)安裝及使用規(guī)則
這篇文章主要為大家介紹了go?micro微服務(wù)proto開(kāi)發(fā)中安裝Protobuf及基本規(guī)范字段的規(guī)則詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Go語(yǔ)言學(xué)習(xí)筆記之文件讀寫(xiě)操作詳解
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言對(duì)文件進(jìn)行讀寫(xiě)操作的方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下2022-05-05

