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()
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()
为所有路由添加中间件:
路由组中间件
通过 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 问题。
- 错误处理:统一捕获和处理错误,提高系统健壮性。