Gin-中间件应用

1. 什么是中间件

中间件是用于拦截 HTTP 请求的函数,在请求被路由处理之前或之后执行。Gin 的中间件机制非常灵活,可以在全局、组、或单个路由上使用。

中间件的基本结构

1
2
3
4
5
6
func ExampleMiddleware(c *gin.Context) {
// 请求前的处理逻辑
c.Next() // 继续后续的中间件或路由处理

// 请求后的处理逻辑
}

2. 日志中间件

日志是 Web 应用的基本需求,用于记录请求的信息。Gin 内置了 Logger 中间件,也可以自定义。

使用内置日志中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

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

func main() {
r := gin.Default() // 默认加载 Logger 和 Recovery 中间件

r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})

r.Run(":8080")
}

自定义日志中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
"log"
"time"

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

func CustomLogger() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()

// 处理请求
c.Next()

// 请求处理后
latency := time.Since(t)
log.Printf("Latency: %v | Status: %d | Path: %s", latency, c.Writer.Status(), c.Request.URL.Path)
}
}

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

r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})

r.Run(":8080")
}

3. 跨域中间件

跨域是前后端分离项目中常见的问题,Gin 不直接提供跨域支持,但可以通过自定义中间件轻松实现。

简单跨域实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

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

func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Authorization")

if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}

c.Next()
}
}

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

r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})

r.Run(":8080")
}

4. 错误处理中间件

在 Web 应用中,统一的错误处理可以提升代码的可维护性和用户体验。

简单的错误处理中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import (
"net/http"

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

func ErrorHandler(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": err,
})
c.Abort()
}
}()

c.Next()
}

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

r.GET("/panic", func(c *gin.Context) {
panic("Something went wrong!")
})

r.Run(":8080")
}

5. 全局、组、和路由中间件

中间件可以在不同的层次上使用:

全局中间件

通过 r.Use() 为所有路由添加中间件:

1
r.Use(CustomLogger())

路由组中间件

通过 Group.Use() 为某个路由组添加中间件:

1
2
adminGroup := r.Group("/admin")
adminGroup.Use(authMiddleware)

单个路由中间件

通过链式调用为某个路由添加中间件:

1
2
3
r.GET("/user/profile", authMiddleware, func(c *gin.Context) {
c.JSON(200, gin.H{"message": "User Profile"})
})

6. 总结

中间件是 Gin 框架中处理通用逻辑的重要工具,可以用于:

  • 日志记录:内置 Logger 或自定义日志逻辑。
  • 跨域支持:通过自定义中间件解决 CORS 问题。
  • 错误处理:统一捕获和处理错误,提高系统健壮性。