不能直接用main.go堆逻辑,因其会导致初始化顺序错乱、测试无法mock、协作时形成“神圣不可修改区”;models与repositories必须物理隔离,且repositories需返回自定义错误类型以支撑精准业务分支处理。

Iris 框架本身不强制目录结构,但 MVC 分层是事实标准;企业级项目必须手动拆分 M、C、V,并额外补上 config、middleware、utils 等支撑层,否则后期维护成本会指数级上升。
为什么不能直接用 main.go 堆逻辑?
初学者常把路由注册、数据库初始化、中间件加载、模板配置全塞进 main.go,看似简单,实则埋下三类隐患:
- 启动文件超过 200 行后,
app.Run()前的初始化顺序极易出错,比如RegisterView在Party创建之后调用会静默失效 - 控制器里直接写 SQL 或调用
http.Get,导致测试无法 mock,单元测试形同虚设 - 多人协作时,没人敢动
main.go—— 它成了“神圣不可修改区”,新功能只能往已有函数里硬塞
models 和 repositories 必须物理隔离
很多教程把结构体和数据库操作混在同一个文件(如 user.go),这违反了单一职责。真实项目中要明确切分:
-
datamodels/user.go:只定义User结构体,带json、gorm或sqlxtag,不引入任何框架依赖 -
repositories/user_repository.go:接收*sql.DB或*gorm.DB,只暴露Create、FindByID等方法,不处理业务规则(如“用户名不能重复”属于 service 层) - 若用 GORM,
AutoMigrate必须放在repositories初始化阶段,而非 controller 中每次调用前检查 —— 否则上线后可能因并发触发多次建表失败
企业级必须加的非 MVC 目录
仅靠 M/C/V 不足以支撑权限校验、日志追踪、配置热更新等需求,以下目录建议在项目初始化时就建好:
-
config/:存放database.yml、jwt.yml,用gopkg.in/yaml.v3解析,避免硬编码连接字符串 -
middleware/:例如auth_middleware.go检查 JWT,返回ctx.StatusCode(401)而非 panic,确保错误可被@ControllerAdvice类机制统一捕获(需自行封装) -
utils/:工具函数如GenerateOrderNo()、MaskPhone(),禁止在 controller 或 service 里写重复逻辑 -
web/views/layouts/:Iris 默认不支持 layout 继承,若用原生html/template,必须手动实现{{template "base" .}}+{{define "content"}},goview 库可简化此过程,但会引入额外依赖
最易被忽略的是 repositories 层的错误返回设计:不要用 error 包裹所有 DB 错误,而是区分 ErrNotFound、ErrDuplicateKey 等自定义错误类型 —— 这样上层 service 才能做精准分支处理,而不是靠字符串匹配 error.Error()。











