🏷️ 标签:Gin Go语言 Gin中间件 中间件原理 跨域中间件 请求拦截 后端开发 📝 简介:一文吃透 Gin 框架中间件,包含中间件执行原理、全局中间件、路由级别中间件、分组中间件、自定义中间件、跨域中间件、日志记录、请求耗时、Next 与 Abort 用法,代码可直接运行,适合零基础入门、课程实训、CSDN 直接发布。
一、前言
在 Gin 框架 Web 开发中,中间件(Middleware) 是核心核心知识点。
中间件可以在请求到达控制器之前、响应返回客户端之前,统一做预处理和后处理,比如:
- 全局日志记录
- 接口请求耗时统计
- 登录身份认证拦截
- 跨域处理
- 请求参数校验
- 统一异常捕获
- 权限校验
Gin 本身基于洋葱模型实现中间件,支持全局中间件、路由中间件、路由组中间件、自定义中间件。
本文从零带你彻底掌握 Gin 中间件所有用法,全覆盖、可直接上手项目开发。
二、Gin 中间件基本原理
2.1 什么是中间件
Gin 中间件本质就是 gin.HandlerFunc 处理器函数。
每一个路由匹配的处理函数,都可以当作中间件。 请求流程:
客户端请求 → 中间件 1 → 中间件 2 → 业务处理 → 响应返回
2.2 两个核心方法
- c.Next()
- 执行后续的中间件和业务逻辑
- 调用完后续逻辑后,会回头继续执行当前 c.Next () 后面的代码
- 实现前置拦截 + 后置收尾
- c.Abort()
- 终止后续所有中间件和业务执行
- 直接返回响应,常用于权限不足、登录拦截
2.3 洋葱模型执行顺序
请求进入 → 依次执行中间件前置逻辑 → 执行业务接口 → 逆序执行中间件后置收尾逻辑 → 返回客户端
三、环境准备
安装 Gin
go get github.com/gin-gonic/gin
基础入口代码:
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.Run(":8080")
}
四、默认自带中间件
4.1 gin.Default()
r := gin.Default()
默认自带两个中间件:
gin.Logger()日志中间件,打印请求方法、路径、状态码、耗时gin.Recovery()崩溃恢复中间件,panic 不导致服务宕机
4.2 不使用默认中间件
如果想自己控制所有中间件,使用:
r := gin.New()
此时没有日志、没有崩溃恢复,需要手动注册。
五、全局中间件
所有请求进来都会经过全局中间件。
5.1 注册全局日志、崩溃恢复
func main() {
r := gin.New()
// 注册全局中间件
r.Use(gin.Logger())
r.Use(gin.Recovery())
r.GET("/hello", func(c *gin.Context) {
c.String(200, "Hello Gin 全局中间件")
})
r.Run(":8080")
}
六、自定义全局中间件(请求耗时案例)
6.1 编写自定义中间件
// 自定义全局中间件:统计请求耗时
func CostTimeMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 前置逻辑:记录开始时间
start := time.Now()
// 执行后续中间件和业务
c.Next()
// 后置逻辑:计算耗时
cost := time.Since(start)
// 请求路径 + 请求方法 + 耗时
path := c.Request.URL.Path
method := c.Request.Method
println("请求路径:", path, "请求方法:", method, "耗时:", cost.String())
}
}
6.2 注册全局使用
func main() {
r := gin.New()
// 注册自定义全局中间件
r.Use(CostTimeMiddleware())
r.GET("/test", func(c *gin.Context) {
c.String(200, "测试自定义中间件")
})
r.Run(":8080")
}
访问接口,自动打印请求耗时。
七、路由级别中间件
只给某一个路由单独绑定中间件,其他路由不生效。
7.1 编写权限中间件
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 模拟校验token
token := c.GetHeader("token")
if token != "123456" {
c.JSON(401, gin.H{
"code": 401,
"msg": "未登录或Token无效",
})
// 终止后续执行
c.Abort()
return
}
// 校验通过,继续往下执行
c.Next()
}
}
7.2 路由单独使用中间件
// 该路由需要经过登录中间件
r.GET("/user/info", AuthMiddleware(), func(c *gin.Context) {
c.JSON(200, gin.H{
"name": "张三",
"age": 25,
})
})
// 该路由不使用中间件
r.GET("/index", func(c *gin.Context) {
c.String(200, "首页无需登录")
})
八、路由组中间件
统一给一组接口添加中间件,适合后台管理接口统一鉴权。
func main() {
r := gin.Default()
// 路由组 + 统一中间件
adminGroup := r.Group("/admin", AuthMiddleware())
{
adminGroup.GET("/user/list", func(c *gin.Context) {
c.JSON(200, gin.H{"msg": "用户列表"})
})
adminGroup.GET("/order/list", func(c *gin.Context) {
c.JSON(200, gin.H{"msg": "订单列表"})
})
}
r.Run(":8080")
}
/admin 下所有接口统一走登录鉴权中间件。
九、跨域中间件(项目必备)
前后端分离项目必用,解决浏览器跨域请求。
自定义跨域中间件
func CorsMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 设置跨域请求头
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
c.Header("Access-Control-Allow-Headers", "Content-Type,Token")
// 处理OPTIONS预检请求
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(200)
return
}
c.Next()
}
}
注册全局生效:
r.Use(CorsMiddleware())
十、c.Next () 与 c.Abort () 核心总结
- c.Next()
- 放行,执行后续中间件和业务
- 后面代码等业务执行完再回头执行,适合统计耗时、日志收尾
2.c.Abort()
- 直接截断请求,不再执行后续中间件和控制器
- 适合登录拦截、权限拒绝、参数错误
十一、中间件使用场景总表格
| 中间件类型 | 使用场景 |
|---|---|
| 全局中间件 | 日志、跨域、请求耗时、全局过滤 |
| 路由中间件 | 单个接口单独鉴权、单独校验 |
| 路由组中间件 | 后台管理接口统一登录拦截 |
| 自定义中间件 | 权限校验、参数过滤、签名验证、日志记录 |
十二、总结
- Gin 中间件基于
gin.HandlerFunc实现,本质就是处理函数。 gin.Default()默认自带日志和崩溃恢复中间件。- 中间件分三种:全局中间件、路由中间件、路由组中间件。
c.Next()实现前后置处理,洋葱模型执行顺序。c.Abort()截断请求,用于登录、权限拦截。- 常用实战中间件:请求耗时、登录鉴权、跨域、日志拦截。
- 中间件是 Gin 框架做统一请求处理、权限控制、日志管理的核心必备技能。
版权声明
本文为原创 Gin 框架中间件完整教程,包含原理、全局 / 路由 / 分组中间件、自定义中间件、跨域中间件、Next 与 Abort 实战,代码可直接运行,适合 CSDN 发布、课程实训、期末作业、面试复习,禁止未经授权转载、抄袭与搬运。