Golang實現(xiàn)自定義recovery中間件
為什么需要實現(xiàn)自定義 recovery 中間件
在 Golang 的 Web 項目中,自定義 recovery 中間件是一種常見的做法,用于捕獲并處理應用程序的運行時錯誤,以避免整個應用程序崩潰并返回對應格式的響應數(shù)據(jù)。
很多三方 web 框架(例如 gin、echo)都提供了官方實現(xiàn)的 recovery 中間件,但是官方實現(xiàn)的中間件并不一定能滿足自己的需求。例如 gin 官方提供的 recovery 中間件,發(fā)生 panic 后會將當前請求的標準狀態(tài)碼置為 500,body 置為空。但是這樣的返回數(shù)據(jù)與格式可能會和自己的項目要求不一致。例如,項目發(fā)生 panic 后是要求標準狀態(tài)碼依然返回 200,body 值為 {"code":-1, "data":nil,"msg":"xxx"},這種場景下,就需要實現(xiàn)自己的 recovery 中間件了。
如何實現(xiàn)自定義 recovery 中間件
如果使用 gin 框架的話,就非常簡單了,因為 gin 提供了完善的中間件功能,遵守 gin 的要求實現(xiàn)滿足自己項目的功能就可以了,簡單示例代碼如下:
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")
}運行起來后,訪問 /test 觸發(fā) panic 后返回了預期的結(jié)果,如下:
$ curl http://127.0.0.1:8080/test
{"code":-1,"data":null,"msg":"server panic"}
接下來再看一個基于原生包 net/http 的一個示例,代碼如下:
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 {
// 打印錯誤信息
log.Println("[Recovery] Panic:", err)
// 打印堆棧跟蹤信息
log.Printf("[Recovery] Stack Trace:\n%s\n", debug.Stack())
// 返回一個適當?shù)腻e誤響應給客戶端
fmt.Fprintf(w, `{"code":-1,"data":null,"msg":"server panic"}`)
}
}()
// 繼續(xù)處理下一個中間件或路由處理函數(shù)
next.ServeHTTP(w, r)
})
}
// 示例的處理函數(shù)
func helloHandler(w http.ResponseWriter, r *http.Request) {
panic("Oops! Something went wrong.") // 模擬一個錯誤
w.Write([]byte("Hello, Recovery Middleware!"))
}
func main() {
// 創(chuàng)建一個多路復用器
mux := http.NewServeMux()
// 注冊中間件
mux.Handle("/test", recoveryMiddleware(http.HandlerFunc(helloHandler)))
// 創(chuàng)建服務器
server := &http.Server{
Addr: ":8080",
Handler: mux,
}
// 啟動服務器
log.Println("Server is running on http://localhost:8080")
log.Fatal(server.ListenAndServe())
}小結(jié)
Web 應用程序在運行時遇到錯誤并拋出 panic 時,自定義的 recovery 中間件將會捕獲panic 并記錄對應的錯誤和堆棧信息,避免應用程序崩潰,并向客戶端發(fā)送適當?shù)腻e誤響應數(shù)據(jù)。對于文本的示例,可以根據(jù)自己的實際需求進行調(diào)整和擴展來實現(xiàn)自定義的 recovery 中間件。
到此這篇關(guān)于Golang實現(xiàn)自定義recovery中間件的文章就介紹到這了,更多相關(guān)go recovery內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang Map value不可尋址使用指針類型代替示例詳解
這篇文章主要為大家介紹了Golang Map value不可尋址使用指針類型代替示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11
Golang10進制轉(zhuǎn)16進制的幾種方法代碼示例
這篇文章主要給大家介紹了關(guān)于Golang10進制轉(zhuǎn)16進制的幾種方法,進制轉(zhuǎn)換是Golang的一些基本操作,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07

