Golang實(shí)現(xiàn)自定義recovery中間件
為什么需要實(shí)現(xiàn)自定義 recovery 中間件
在 Golang 的 Web 項(xiàng)目中,自定義 recovery 中間件是一種常見的做法,用于捕獲并處理應(yīng)用程序的運(yùn)行時(shí)錯(cuò)誤,以避免整個(gè)應(yīng)用程序崩潰并返回對應(yīng)格式的響應(yīng)數(shù)據(jù)。
很多三方 web 框架(例如 gin、echo)都提供了官方實(shí)現(xiàn)的 recovery 中間件,但是官方實(shí)現(xiàn)的中間件并不一定能滿足自己的需求。例如 gin 官方提供的 recovery 中間件,發(fā)生 panic 后會將當(dāng)前請求的標(biāo)準(zhǔn)狀態(tài)碼置為 500,body 置為空。但是這樣的返回?cái)?shù)據(jù)與格式可能會和自己的項(xiàng)目要求不一致。例如,項(xiàng)目發(fā)生 panic 后是要求標(biāo)準(zhǔn)狀態(tài)碼依然返回 200,body 值為 {"code":-1, "data":nil,"msg":"xxx"},這種場景下,就需要實(shí)現(xiàn)自己的 recovery 中間件了。
如何實(shí)現(xiàn)自定義 recovery 中間件
如果使用 gin 框架的話,就非常簡單了,因?yàn)?gin 提供了完善的中間件功能,遵守 gin 的要求實(shí)現(xiàn)滿足自己項(xiàng)目的功能就可以了,簡單示例代碼如下:
package main import ( "github.com/gin-gonic/gin" "log" "net/http" "runtime" ) func Recovery() gin.HandlerFunc { return func(c *gin.Context) { defer func() { if err := recover(); err != nil { const size = 64 << 10 stack := make([]byte, size) stack = stack[:runtime.Stack(stack, false)] log.Printf("[GinPanic] %s\n", string(stack)) c.JSON(http.StatusOK, struct { Code int `json:"code"` Data interface{} `json:"data"` Msg string `json:"msg"` }{ Code: -1, Data: nil, Msg: "server panic", }) c.Abort() } }() c.Next() } }
使用示例如下:
package main import ( "github.com/gin-gonic/gin" "runtime" ) func main() { r := gin.New() r.Use(Recovery()) r.GET("/test", func(c *gin.Context) { panic("Oops! Something went wrong.") }) r.Run(":8080") }
運(yùn)行起來后,訪問 /test 觸發(fā) panic 后返回了預(yù)期的結(jié)果,如下:
$ curl http://127.0.0.1:8080/test
{"code":-1,"data":null,"msg":"server panic"}
接下來再看一個(gè)基于原生包 net/http 的一個(gè)示例,代碼如下:
package main import ( "fmt" "log" "net/http" "runtime/debug" ) // 自定義的recovery中間件 func recoveryMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if err := recover(); err != nil { // 打印錯(cuò)誤信息 log.Println("[Recovery] Panic:", err) // 打印堆棧跟蹤信息 log.Printf("[Recovery] Stack Trace:\n%s\n", debug.Stack()) // 返回一個(gè)適當(dāng)?shù)腻e(cuò)誤響應(yīng)給客戶端 fmt.Fprintf(w, `{"code":-1,"data":null,"msg":"server panic"}`) } }() // 繼續(xù)處理下一個(gè)中間件或路由處理函數(shù) next.ServeHTTP(w, r) }) } // 示例的處理函數(shù) func helloHandler(w http.ResponseWriter, r *http.Request) { panic("Oops! Something went wrong.") // 模擬一個(gè)錯(cuò)誤 w.Write([]byte("Hello, Recovery Middleware!")) } func main() { // 創(chuàng)建一個(gè)多路復(fù)用器 mux := http.NewServeMux() // 注冊中間件 mux.Handle("/test", recoveryMiddleware(http.HandlerFunc(helloHandler))) // 創(chuàng)建服務(wù)器 server := &http.Server{ Addr: ":8080", Handler: mux, } // 啟動服務(wù)器 log.Println("Server is running on http://localhost:8080") log.Fatal(server.ListenAndServe()) }
小結(jié)
Web 應(yīng)用程序在運(yùn)行時(shí)遇到錯(cuò)誤并拋出 panic 時(shí),自定義的 recovery 中間件將會捕獲panic 并記錄對應(yīng)的錯(cuò)誤和堆棧信息,避免應(yīng)用程序崩潰,并向客戶端發(fā)送適當(dāng)?shù)腻e(cuò)誤響應(yīng)數(shù)據(jù)。對于文本的示例,可以根據(jù)自己的實(shí)際需求進(jìn)行調(diào)整和擴(kuò)展來實(shí)現(xiàn)自定義的 recovery 中間件。
到此這篇關(guān)于Golang實(shí)現(xiàn)自定義recovery中間件的文章就介紹到這了,更多相關(guān)go recovery內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang Map value不可尋址使用指針類型代替示例詳解
這篇文章主要為大家介紹了Golang Map value不可尋址使用指針類型代替示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11Golang10進(jìn)制轉(zhuǎn)16進(jìn)制的幾種方法代碼示例
這篇文章主要給大家介紹了關(guān)于Golang10進(jìn)制轉(zhuǎn)16進(jìn)制的幾種方法,進(jìn)制轉(zhuǎn)換是Golang的一些基本操作,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07Golang巧用defer進(jìn)行錯(cuò)誤處理的方法
錯(cuò)誤處理是程序的重要組成部分,有效且優(yōu)雅的處理錯(cuò)誤是大多數(shù)程序員的追求,下面這篇文章主要給大家介紹了關(guān)于Golang中巧用defer進(jìn)行錯(cuò)誤處理的方法,文中通過示例介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-05-05深入了解Golang網(wǎng)絡(luò)編程N(yùn)et包的使用
net包主要是增加?context?控制,封裝了一些不同的連接類型以及DNS?查找等等,同時(shí)在有需要的地方引入?goroutine?提高處理效率。本文主要和大家分享下在Go中網(wǎng)絡(luò)編程的實(shí)現(xiàn),需要的可以參考一下2022-07-07golang根據(jù)生日計(jì)算星座和屬相實(shí)例
這篇文章主要為大家介紹了golang根據(jù)生日計(jì)算星座和屬相的示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Go語言實(shí)現(xiàn)的一個(gè)簡單Web服務(wù)器
這篇文章主要介紹了Go語言實(shí)現(xiàn)的一個(gè)簡單Web服務(wù)器,本文先是給出一個(gè)使用http包建立的Web服務(wù)器源碼,并對比了其它編程語言,需要的朋友可以參考下2014-10-10GoFrame框架Scan類型轉(zhuǎn)換實(shí)例
這篇文章主要為大家介紹了GoFrame框架Scan類型轉(zhuǎn)換的實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06