app.group()本质是带前缀的中间件容器,不响应请求,仅声明后续路由自动添加前缀;必须显式调用如get()/post()才注册真实路由,且嵌套分组不自动继承父级中间件,需手动传入或单独绑定。

用 app.Group() 创建路径前缀分组
分组本质是带前缀的中间件容器,不是真实路由,也不会响应请求。比如 api := app.Group("/api") 只是声明“接下来挂载的路由都自动加 /api 前缀”,它本身不注册任何 handler。
常见错误是写完 app.Group("/api") 就以为路由已生效,结果访问 /api/users 404——必须显式调用 api.Get("/users", handler) 才真正注册。
-
app.Group("/v1")和app.Group("/v1/")效果相同,末尾斜杠会被标准化 - 分组支持链式调用:
app.Group("/admin").Use(auth).Get("/dashboard", h) - 分组不继承父级
app.Use()的中间件,除非你手动传进去
嵌套分组时中间件作用域只限当前层级
子分组不会自动获得父分组的中间件。例如:
v1 := app.Group("/v1")
v1.Use(auth)
users := v1.Group("/users") // ← 这里不会自动带上 auth
users.Get("/list", handler) // ← 不会触发 auth 中间件!
正确做法是显式传递或在子分组上重新绑定:
- 方案一:在创建子分组时传入中间件 ——
users := v1.Group("/users", auth) - 方案二:对子分组单独调用
Use()——users.Use(auth) - 方案三:直接在子路由上绑定 ——
users.Get("/list", auth, handler)
注意:嵌套层级不影响执行顺序,只影响中间件是否被挂载到该分组下的路由上。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
分组 + 路由方法组合的典型写法
实际项目中常把模块逻辑收拢在分组内,比如用户相关接口统一放在 /api/v1/users 下:
api := app.Group("/api")
v1 := api.Group("/v1")
users := v1.Group("/users", jwtAuth, rateLimit)
users.Get("/", listUsers)
users.Get("/:id", getUser)
users.Post("/", createUser)
users.Put("/:id", updateUser)
users.Delete("/:id", deleteUser)
这段代码注册的实际路径是 GET /api/v1/users、POST /api/v1/users 等,且每个都自动经过 jwtAuth 和 rateLimit。
- 所有中间件按书写顺序执行:
jwtAuth → rateLimit → handler - 如果某个中间件返回非
nilerror(如 token 无效),后续中间件和 handler 都不会执行 - 中间件函数签名必须是
func(*fiber.Ctx) error,漏掉return或误调c.Next()会导致流程失控
别把 app.Use() 当分组用
app.Use("/api", middleware) 看起来像分组,但它是前缀匹配中间件,语义完全不同:
- 它会拦截所有以
/api开头的路径,包括/api/foo/bar/baz,哪怕你根本没定义这个路由 - 它对所有 HTTP 方法生效(GET/POST/PUT/DELETE…),而分组下的
.Get()只响应 GET - 它无法和
Group那样清晰表达“这一组路由属于一个业务模块”
所以除非你要做全局路径前缀拦截(比如静态文件服务、子应用挂载),否则优先选 Group。
嵌套分组本身不复杂,难的是中间件绑定时机和作用域的理解——写错一层,就可能让鉴权跳过或限流失效,这类问题在线上往往静默发生,不容易被日志捕获。










