Gin框架中间件详解
Gin框架中间件详解
1. 中间件绑定路由的几种方式
1.1 全局中间件
package main
import "github.com/gin-gonic/gin"
func GlobalMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 中间件逻辑
c.Next()
}
}
func main() {
r := gin.Default()
// 注册全局中间件(对所有路由生效)
r.Use(GlobalMiddleware())
r.GET("/hello", func(c *gin.Context) {
c.String(200, "Hello World")
})
r.Run(":8080")
}
1.2 路由组中间件
func main() {
r := gin.Default()
// 为路由组注册中间件
api := r.Group("/api", ApiMiddleware())
// 或者使用Use方法
// api := r.Group("/api")
// api.Use(ApiMiddleware())
api.GET("/users", func(c *gin.Context) {
c.String(200, "用户列表")
})
api.GET("/products", func(c *gin.Context) {
c.String(200, "产品列表")
})
}
func ApiMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// API特定中间件逻辑
c.Next()
}
}
1.3 单个路由中间件
func main() {
r := gin.Default()
// 为单个路由注册中间件
r.GET("/admin", AuthMiddleware(), func(c *gin.Context) {
c.String(200, "管理员页面")
})
// 多个中间件
r.POST("/upload", LogMiddleware(), AuthMiddleware(), UploadHandler)
}
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 认证逻辑
c.Next()
}
}
func LogMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 日志记录逻辑
c.Next()
}
}
1.4 链式调用多个中间件
func main() {
r := gin.Default()
// 链式注册多个中间件
adminGroup := r.Group("/admin")
adminGroup.Use(LogMiddleware(), AuthMiddleware(), AdminCheckMiddleware())
adminGroup.GET("/dashboard", func(c *gin.Context) {
c.String(200, "管理面板")
})
}
2. Next() 和 Abort() 函数
2.1 Next() 函数
func LoggerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 请求处理前
start := time.Now()
// 执行后续的中间件和处理函数
c.Next()
// 请求处理后
latency := time.Since(start)
fmt.Printf("请求 %s 耗时 %v\n", c.Request.URL.Path, latency)
}
}
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.JSON(401, gin.H{"error": "未授权"})
c.Abort() // 终止后续处理
return
}
// 验证token...
c.Next() // 继续执行后续中间件
}
}
2.2 Abort() 函数
func RateLimitMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
if isRateLimited(c.ClientIP()) {
c.JSON(429, gin.H{"error": "请求过于频繁"})
c.Abort() // 立即终止,不会执行后续中间件
return
}
c.Next()
}
}
// AbortWithStatus() - 终止并设置状态码
func MaintenanceMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
if isMaintenanceMode {
c.AbortWithStatusJSON(503, gin.H{"message": "系统维护中"})
return
}
c.Next()
}
}
// AbortWithError() - 终止并返回错误
func ErrorHandlerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
c.AbortWithError(500, fmt.Errorf("内部错误: %v", err))
}
}()
c.Next()
}
}
3. 中间件的 Set 和 Get 操作
3.1 设置和获取值
func UserMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 设置值到上下文
user := getUserFromToken(c)
c.Set("user", user)
c.Set("request_id", generateRequestID())
c.Next()
}
}
func UserProfileHandler(c *gin.Context) {
// 从上下文获取值
if user, exists := c.Get("user"); exists {
if userInfo, ok := user.(*User); ok {
c.JSON(200, gin.H{"user": userInfo})
return
}
}
// 获取值并检查类型
if requestID, exists := c.Get("request_id"); exists {
fmt.Printf("Request ID: %s\n", requestID)
}
c.JSON(400, gin.H{"error": "用户信息不存在"})
}
3.2 完整的示例
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"time"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
r := gin.Default()
// 全局中间件
r.Use(LoggerMiddleware())
r.Use(AuthMiddleware())
// 路由组中间件
api := r.Group("/api")
api.Use(SetRequestInfoMiddleware())
api.GET("/user", GetUserHandler)
api.POST("/upload", UploadHandler)
r.Run(":8080")
}
func LoggerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
c.Next()
latency := time.Since(start)
fmt.Printf("[%s] %s %s - %v\n",
time.Now().Format("2006-01-02 15:04:05"),
c.Request.Method,
c.Request.URL.Path,
latency,
)
}
}
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(401, gin.H{"error": "需要认证"})
return
}
// 模拟用户验证
user := &User{ID: 1, Name: "张三"}
c.Set("user", user)
c.Next()
}
}
func SetRequestInfoMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("request_time", time.Now())
c.Set("client_ip", c.ClientIP())
c.Next()
}
}
func GetUserHandler(c *gin.Context) {
user, _ := c.Get("user")
requestTime, _ := c.Get("request_time")
clientIP, _ := c.Get("client_ip")
c.JSON(200, gin.H{
"user": user,
"request_time": requestTime,
"client_ip": clientIP,
})
}
func UploadHandler(c *gin.Context) {
// 检查用户权限
if user, exists := c.Get("user"); exists {
if u, ok := user.(*User); ok {
if u.ID != 1 { // 简单的权限检查
c.AbortWithStatusJSON(403, gin.H{"error": "权限不足"})
return
}
}
}
// 处理上传逻辑
c.JSON(200, gin.H{"message": "上传成功"})
}
3.3 中间件执行顺序的重要性
func main() {
r := gin.Default()
// 中间件执行顺序:Logger → Auth → SetInfo
r.Use(LoggerMiddleware()) // 最先执行
r.Use(AuthMiddleware()) // 其次执行
r.Use(SetRequestInfoMiddleware()) // 最后执行
r.GET("/test", func(c *gin.Context) {
// 在这里可以访问所有中间件设置的值
c.JSON(200, gin.H{
"message": "测试路由",
})
})
}
关键点总结
- 绑定方式:全局中间件、路由组中间件、单个路由中间件
- Next():继续执行后续中间件和处理函数
- Abort():终止当前请求的后续处理
- Set/Get:在中间件间传递数据,使用类型断言确保类型安全
- 执行顺序:中间件按照注册顺序执行,Next()前后的代码分别在请求前后执行
这些功能使得Gin中间件非常灵活,可以用于认证、日志、限流、数据预处理等多种场景。

浙公网安备 33010602011771号