効率的なミドルウェアを1つ作成する方法
構成要素
ミドルウェアには2つの部分があります。
1つ目は、ミドルウェアを初期化したときに一度実行されます。ここで、すべてのグローバルオブジェクト、論理などを設定します。アプリケーションのライフタイムで1回だけ発生します。
2つ目は、すべてのリクエストで実行されます。たとえば、データベースミドルウェアは、単に「グローバル」データベースオブジェクトをコンテキストに挿入します。いったんコンテキスト内に入ると、他のミドルウェアやハンドラ関数から取得できます。
func funcName(params string) gin.HandlerFunc {
// <---
// This is part one
// --->
// The following code is an example
if err := check(params); err != nil {
panic(err)
}
return func(c *gin.Context) {
// <---
// This is part two
// --->
// The following code is an example
c.Set("TestVar", params)
c.Next()
}
}
実行処理
まず、次のサンプルコードがあります
func main() {
router := gin.Default()
router.Use(globalMiddleware())
router.GET("/rest/n/api/*some", mid1(), mid2(), handler)
router.Run()
}
func globalMiddleware() gin.HandlerFunc {
fmt.Println("globalMiddleware...1")
return func(c *gin.Context) {
fmt.Println("globalMiddleware...2")
c.Next()
fmt.Println("globalMiddleware...3")
}
}
func handler(c *gin.Context) {
fmt.Println("exec handler.")
}
func mid1() gin.HandlerFunc {
fmt.Println("mid1...1")
return func(c *gin.Context) {
fmt.Println("mid1...2")
c.Next()
fmt.Println("mid1...3")
}
}
func mid2() gin.HandlerFunc {
fmt.Println("mid2...1")
return func(c *gin.Context) {
fmt.Println("mid2...2")
c.Next()
fmt.Println("mid2...3")
}
}
構成要素に記載されているように、ginプロセスを実行すると、1つ目がまず実行され、次の情報が出力されます
globalMiddleware...1
mid1...1
mid2...1
そしてinitの順序は次のようになります:
globalMiddleware...1
|
v
mid1...1
|
v
mid2...1
curl -v localhost:8080/rest/n/api/some
という1つのリクエストをcurlすると、2つ目はミドルウェアを実行し、次の情報を出力します
globalMiddleware...2
mid1...2
mid2...2
exec handler.
mid2...3
mid1...3
globalMiddleware...3
言い換えると、実行順序は次のようになります。
globalMiddleware...2
|
v
mid1...2
|
v
mid2...2
|
v
exec handler.
|
v
mid2...3
|
v
mid1...3
|
v
globalMiddleware...3