カスタムリカバリの挙動
Ginの組み込みgin.Recovery()ミドルウェアは、リクエスト処理中に発生したあらゆるpanicをキャッチし、500レスポンスを書き込み、サーバーを稼働し続けます。リカバリ時の挙動を制御したい場合 — 例えばpanicをユーザーに通知したり、データベースに保存したり、エラートラッキングサービスに送信したりする場合 — は、代わりにgin.CustomRecovery()を使用します。
gin.CustomRecovery()は、func(c *gin.Context, recovered any)というシグネチャを持つハンドラを受け取ります。recoveredの値は、panic()に渡されたものです。ハンドラ内でどのように応答するかを決定し、その後c.AbortWithStatus()(または別のabortメソッド)を呼び出して、残りのハンドラがスキップされるようにします。
package main
import ( "fmt" "net/http"
"github.com/gin-gonic/gin")
func main() { // デフォルトではミドルウェアなしのルーターを作成 r := gin.New()
// グローバルミドルウェア // GIN_MODE=releaseを設定していても、Loggerミドルウェアはgin.DefaultWriterにログを書き込みます。 // デフォルトでは gin.DefaultWriter = os.Stdout r.Use(gin.Logger())
// Recoveryミドルウェアはあらゆるpanicからリカバリし、panicがあった場合は500を書き込みます。 r.Use(gin.CustomRecovery(func(c *gin.Context, recovered any) { if err, ok := recovered.(string); ok { c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err)) } c.AbortWithStatus(http.StatusInternalServerError) }))
r.GET("/panic", func(c *gin.Context) { // 文字列でpanic -- カスタムミドルウェアはこれをデータベースに保存したり、ユーザーに通知したりできます panic("foo") })
r.GET("/", func(c *gin.Context) { c.String(http.StatusOK, "ohai") })
// 0.0.0.0:8080でリッスンしてサーブ r.Run(":8080")}テスト
# panicをトリガー;カスタムリカバリハンドラがメッセージを返しますcurl http://localhost:8080/panic# => error: foo
# 通常のリクエストは引き続き動作しますcurl http://localhost:8080/# => ohai