2.4. 程序结构
说明
程序结构很重要,决定了我们如何快速定位到需要的代码文件。随着项目功能的增加,代码会越来越多,合理的程序结构保证了复杂项目的可维护性。
PHP 的 Laravel 框架已经是最知名 Web 开发框架之一,它的程序结构清晰,照顾到 Web/API 开发的方方面面。故本项目,我们不会重新发明自己的轮子,而是站在巨人的肩膀上,程序结构大体参考 Laravel 框架。
FAQ
设计程序结构时,常见问题:
问:那么多目录,会不会对性能有影响?
答: 不会。Go 是编译语言,所有的代码最终会被编译为一个可执行文件。文件的多少以及目录的层级,不会影响程序性能。
问:是不是所有项目代码写在 main.go 里也可以运行?
答: 可以。但是可维护性会很低。一般一个文件中上千行代码,就已经很难维护。一个项目随随便便成千上万行代码。如果你想报复雇主,可以这么做,离职后他将很难找到愿意维护你代码的人。
问:划分程序结构的目的是什么?
答: 为了方便开发者在代码中自由驰骋,而不会迷路。
程序结构
这里罗列出来程序结构,让大家心里有个底,项目开发时我们会逐渐添加这些目录。
结构如下:
.├── app // 程序具体逻辑代码
│ ├── cmd // 命令
│ │ ├── cache.go
│ │ ├── cmd.go
│ │ ├── key.go
│ │ ├── make // make 命令及子命令
│ │ │ ├── make.go
│ │ │ ├── make_apicontroller.go
│ │ │ ├── make_cmd.go
│ │ │ ├── make_factory.go
│ │ │ ├── make_migration.go
│ │ │ ├── make_model.go
│ │ │ ├── make_policy.go
│ │ │ ├── make_request.go
│ │ │ ├── make_seeder.go
│ │ │ └── stubs // make 命令的模板
│ │ │ ├── apicontroller.stub
│ │ │ ├── cmd.stub
│ │ │ ├── factory.stub
│ │ │ ├── migration.stub
│ │ │ ├── model
│ │ │ │ ├── model.stub
│ │ │ │ ├── model_hooks.stub
│ │ │ │ └── model_util.stub
│ │ │ ├── policy.stub
│ │ │ ├── request.stub
│ │ │ └── seeder.stub
│ │ ├── migrate.go
│ │ ├── play.go
│ │ ├── seed.go
│ │ └── serve.go
│ ├── http // http 请求处理逻辑
│ │ ├── controllers // 控制器,存放 API 和视图控制器
│ │ │ ├── api // API 控制器,支持多版本的 API 控制器
│ │ │ │ └── v1 // v1 版本的 API 控制器
│ │ │ │ ├── users_controller.go
│ │ │ │ └── ...
│ │ └── middlewares // 中间件
│ │ ├── auth_jwt.go
│ │ ├── guest_jwt.go
│ │ ├── limit.go
│ │ ├── logger.go
│ │ └── recovery.go
│ ├── models // 数据模型
│ │ ├── user // 单独的模型目录
│ │ │ ├── user_hooks.go // 模型钩子文件
│ │ │ ├── user_model.go // 模型主文件
│ │ │ └── user_util.go // 模型辅助方法
│ │ └── ...
│ ├── policies // 授权策略目录
│ │ ├── category_policy.go
│ │ └── ...
│ └── requests // 请求验证目录(支持表单、标头、Raw JSON、URL Query)
│ ├── validators // 自定的验证规则
│ │ ├── custom_rules.go
│ │ └── custom_validators.go
│ ├── user_request.go
│ └── ...
├── bootstrap // 程序模块初始化目录
│ ├── app.go
│ ├── cache.go
│ ├── database.go
│ ├── logger.go
│ ├── redis.go
│ └── route.go
├── config // 配置信息目录
│ ├── app.go
│ ├── captcha.go
│ ├── config.go
│ ├── database.go
│ ├── jwt.go
│ ├── log.go
│ ├── mail.go
│ ├── pagination.go
│ ├── redis.go
│ ├── sms.go
│ └── verifycode.go
├── database // 数据库相关目录
│ ├── database.db // sqlite 数据文件(加入到 .gitignore 中)
│ ├── factories // 模型工厂目录
│ │ ├── user_factory.go
│ │ └── ...
│ ├── migrations // 数据库迁移目录
│ │ ├── 2021_12_21_102259_create_users_table.go
│ │ ├── 2021_12_21_102340_create_categories_table.go
│ │ └── ...
│ └── seeders // 数据库填充目录
│ ├── users_seeder.go
│ ├── ...
├── pkg // 内置辅助包
│ ├── app
│ ├── auth
│ ├── cache
│ ├── captcha
│ ├── config
│ └── ...
├── public // 静态文件存放目录
│ ├── css
│ ├── js
│ └── uploads // 用户上传文件目录
│ └── avatars // 用户上传头像目录
├── routes // 路由
│ ├── api.go
│ └── web.go
├── storage // 内部存储目录
│ ├── app
│ └── logs // 日志存储目录
│ ├── 2021-12-28.log
│ ├── 2021-12-29.log
│ ├── 2021-12-30.log
│ └── logs.log
└── tmp // air 的工作目录
├── .env // 环境变量文件
├── .env.example // 环境变量示例文件
├── .gitignore // git 配置文件
├── .air.toml // air 配置文件
├── .editorconfig // editorconfig 配置文件
├── go.mod // Go Module 依赖配置文件
├── go.sum // Go Module 模块版本锁定文件
├── main.go // Gohub 程序主入口
├── Makefile // 自动化命令文件
├── readme.md // 项目 readme