路由拆分必须用party,子包不能直接调用app.get;应导出register函数接收party实例注册路由,路径前缀逐层拼接,中间件作用域按全局/分组/子路由严格隔离。

路由拆分必须用 Party,不能直接在子包里调用 app.Get
很多人把路由函数移到单独的 handlers 或 routes 包后,直接在子包里写 app.Get("/user", handler),结果启动没报错但路由完全不生效。根本原因是:Iris 的 app 实例是主包创建的,子包拿不到它,也无法修改其内部路由表。正确做法是让子包只暴露“注册函数”,由主包统一传入 Party 实例来挂载。
常见错误现象:go run main.go 启动成功、无日志、访问 404;或部分路由能访问、部分完全消失。
- 子包应定义类似
func SetupUserRoutes(api *iris.Application)或更推荐的func SetupUserRoutes(party iris.Party) - 主包中先调用
usersAPI := app.Party("/api/v1/users"),再传给子包函数 - 子包内所有
.Get/.Post都必须作用于传入的party,而非全局app - 不要在子包里 import 主包(如
main),否则造成循环依赖
Party 是挂载点,不是命名空间 —— 路径前缀必须显式写出
有人以为 app.Party("/admin") 创建了一个叫 admin 的独立路由空间,之后在子包里写 party.Get("/users") 就自动变成 /admin/users。这没错,但容易忽略:如果子包自己又调了一次 party.Party("/v2"),那路径就变成 /admin/v2/users,而主包并不知情。路径拼接是逐层累积的,不是覆盖。
当代理已经知道网站路由或内容URL,并且在启动前需要有效的sitemap XML、sitemap索引或robots.txt引用时,请使用sitemap。这是一个发布构件技能,而不是爬虫或SEO平台。
- 主包创建
admin := app.Party("/admin"),已固定前缀 - 子包接收
admin后,admin.Get("/users")→/admin/users - 若子包再写
v2 := admin.Party("/v2"),然后v2.Get("/users")→/admin/v2/users - 路径最终形态取决于每一层
Party的字符串拼接,没有“重置”机制
中间件绑定要分清层级:全局、分组、子路由三者不互通
你可能想在用户模块加 JWT 验证,在文章模块加限流,但发现某个中间件影响了所有路由。这是因为 Party 支持传入中间件,但它的作用范围仅限该分组及其子分组,不会漏到其他 Party 下——前提是别在主 app 上误加。
- 全局中间件用
app.Use(middleware),影响所有路由(包括未分组的) - 分组中间件写在
Party调用时:usersAPI := app.Party("/users", jwtMiddleware, loggerMiddleware) - 子路由级中间件只能用
party.Get("/x", middleware1, handler)这种链式写法 - 注意:分组中间件对子分组也生效,比如
api.Party("/v1", m1).Party("/users", m2),m1和m2都会执行
子包路由函数如何组织才利于测试和复用
直接把 handler 函数全塞进一个 setup.go 里,时间一长就难维护。真正可扩展的结构是:每个业务子包导出一个 Register 函数,接收 iris.Party 和可选依赖(如数据库实例),不依赖全局变量。
- 目录结构建议:
app/routes/users/register.go导出Register(party iris.Party, db *sql.DB) - handler 函数放在
app/handlers/users/下,保持纯逻辑,不碰iris.Context以外的东西 - 测试时可直接传入 mock
iris.Party(用iris.New().Party("")即可),验证是否注册了预期的路由 - 避免在子包里调用
iris.Compression等全局配置,压缩应该由主包统一决定
最常被忽略的一点:Iris 的 Party 不是“声明式”的路由容器,而是运行时动态构建的路由分支。这意味着你在子包里调用 party.Get 的顺序,就是最终路由匹配的优先级顺序——哪怕它们物理上分布在不同文件里。别指望靠文件名排序来控制优先级,得靠代码执行顺序。










