全局中间件必须在r.Run()前注册,对所有路由(含404)无条件生效;注册须早于任何路由定义,作用于*gin.Engine实例,执行顺序遵循洋葱模型,先注册的前置逻辑先执行、后置逻辑后执行。

全局中间件必须在 r.Run() 之前注册,且对所有路由(包括 404)生效——它不是“默认开启”,而是“无条件拦截”。
全局中间件注册位置和时机
注册点只能是 main() 启动流程中、r.Run() 调用前的任意位置,但必须早于任何 GET/POST/Group 调用。常见错误是把它塞进某个 handler 或 init 函数里,那根本不会执行。
-
r.Use()必须作用于*gin.Engine实例,比如r := gin.New()或gin.Default()返回的对象 - 如果用
gin.Default(),它已自动注册gin.Logger()和gin.Recovery(),再调r.Use()是追加,不是覆盖 - 顺序敏感:先注册的中间件,前置逻辑先执行;后注册的,后置逻辑先执行(洋葱模型)
全局中间件会拦截 404 请求
这是最容易被忽略的一点:只要路径没匹配到任何路由,请求仍会完整走完所有全局中间件的 c.Next() 前后逻辑,最后才落到 404 处理器。如果你在中间件里做了耗时操作(如远程鉴权、日志写磁盘),404 请求也会被拖慢。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 想跳过 404 场景?不能靠“判断路径是否存在”,而应改用路由组中间件或在中间件内检查
c.HandlerName() == "github.com/gin-gonic/gin.(*Engine).handle404" - 高频健康检查接口(如
/health)若挂了全局中间件,可能因日志/鉴权等导致延迟升高,需单独剥离
避免在全局中间件里滥用 c.Copy()
只有当你明确需要在 goroutine 中安全访问 *gin.Context 字段时,才调 c.Copy()。95% 的全局中间件(日志、计时、Header 注入)完全不需要它。
- 错误写法:
go func() { log.Printf("path: %s", c.Request.URL.Path) }()——c是闭包捕获,非线程安全 - 正确轻量写法:
path := c.Request.URL.Path; go func() { log.Printf("path: %s", path) }() - 真要用
c.Copy(),确保只在必要分支里调用,且后续确实用了拷贝体;否则纯属浪费内存和 CPU
全局中间件与路由组中间件的关系
全局中间件和路由组中间件不叠加、不继承,只是按注册顺序串成一条链。一个请求进来,会依次执行:全局中间件 A 前置 → 全局中间件 B 前置 → 路由组中间件 C 前置 → handler → C 后置 → B 后置 → A 后置。
- 不要以为“全局注册了 auth,group 就不用再注册”——如果 group 需要额外校验(如 RBAC),必须显式
group.Use() - 路由组中间件不会影响兄弟 group,也不会穿透到其他 group 下的子 group,作用域严格受限
- 调试时可用
c.HandlerNames()查看当前请求实际触发了哪些中间件函数名
真正难的不是注册,而是厘清「这个逻辑到底该放全局、group 还是单个路由」——比如用户身份解析,放在全局意味着所有静态资源请求也要走一遍 JWT 解析;而放在 API group 里,就只影响 /api 下路径。这种粒度选择,比语法本身更影响性能和可维护性。


















