「Go フレームワーク」 ジン フレームワークはパニックをどのように処理しますか?

この記事では、gin フレームワークにおける Recovery のアプリケーションを紹介します。まず、golangではサブコルーチンでパニックが発生するとメインコルーチンも終了してしまいます。次のように:

package main

import (
	"github.com/gin-gonic/gin"
)

func main() {
    
    
	r := gin.Default()

    // 在子协程中引起panic,主协程也会退出
	go func() {
    
    
		panic("hello world")
	}()
    
	// Listen and Server in 0.0.0.0:8080
	r.Run(":8080")
}


パニックは、処理できないエラーとして説明されます。Web サービスでは、サービスがクラッシュします。もちろん、これは運用環境では受け入れられません。では、パニックが発生したときにパニックをどのように捉えて、サービスを正常に実行し続けることができるのでしょうか?
golangで提供されているrecover関数です。リカバリ機能はパニックエラーを捕捉し、プログラムの通常の動作を復元できます。
次に、recover 関数が gin フレームワークにどのように適用されるかを見てみましょう。
まず最初に言及したいのは、gin フレームワークのリカバリ ミドルウェアです。gin では、このミドルウェアはパニックを捕捉し、サービスがダウンしないようにするために使用されます。gin.Default() 関数を使用して gin オブジェクトを構築すると、リカバリ ミドルウェアがデフォルトで登録されます。

func Default() *Engine {
    
    
	debugPrintWARNINGDefault()
	engine := New()
    //  注册了Recovery中间件
	engine.Use(Logger(), Recovery())
	return engine
}

次に、Recovery() ミドルウェアが何を行うかを見てみましょう。

Recovery() 関数は次のように定義されます。

func Recovery() HandlerFunc {
    
    
	return RecoveryWithWriter(DefaultErrorWriter)
}

ここでの DefaultErrorWriter は、デフォルトの出力ポート (os.Stderr) です。つまり、エラーが出力される場所です。

次に、RecoveryWithWriter 関数の実装を見てみましょう。

// 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)
}

ここには、defaultHandleRecovery というパラメーターがあります。その実装を見てみましょう。

func defaultHandleRecovery(c *Context, err any) {
    
    
	c.AbortWithStatus(http.StatusInternalServerError)
}

内部サーバーエラーを表すステータスコード 500 を書き込み、リクエストを終了します。

ここでの重要なポイントは CustomRecoveryWithWriter の実装です。コードは非常に長いので、いくつかのセクションに分けて見てみましょう。主に次の
ここに画像の説明を挿入します
3 つの部分に分かれています。

ログを out に出力します。これが上記の DefaultErrorWriter、os.Stderr です。
遅延実行部分を延期します。
c.Next() 通常のリクエストプロセッサ部分。

ここで注意すべき点は次のとおりです。

回復関数は遅延で呼び出す必要があります。defer は関数が戻るときに呼び出されるため、パニックが発生したときに関数が戻るようになり、パニックをキャプチャできるようになります。
ミドルウェアとして実行するということは、各リクエスト プロセッサがミドルウェアによってラップされることを意味します。これは、各リクエスト プロセッサがこの遅延機能を持つことと同等です。
defer 関数では、パニックがキャプチャされた場合、パニックの詳細が詳細に記録され、指定された出力、つまり関数で指定された out パラメーター (デフォルトは os.Stderr) に送信できます。他のファイルまたは Sentry を指定できます。

gin では、Web サービスの堅牢性を確保するのはこのミドルウェアのアプリケーションです。もちろん、他の Web フレームワークも同じ仕組みを持ち、実装原理も同じです。

おすすめ

転載: blog.csdn.net/m0_73728511/article/details/133325772