Go 通用项目结构
关于 Go 项目的目录结构如何设计这一问题?Go 官方其实并没有定义标准的项目结构分层,但社区维护了一个 project-layout 仓库,其中包含了一个通用的项目结构示例,大家在实践中基本会遵循这个规范。
下面是一个通用的项目结构示例,并且可能因项目的规模、需求和偏好而有所不同。
project/
├── api/
│ ├── handler/ # API请求处理程序
│ ├── middleware/ # API中间件
│ └── router.go # 路由定义
├── cmd/
│ ├── app/ # 应用程序入口点
│ └── cli/ # 命令行接口入口点
├── config/ # 配置文件和配置相关代码
├── internal/ # 私有应用程序和库代码
│ ├── model/ # 数据库模型
│ ├── repository/ # 数据库访问层
│ ├── service/ # 业务逻辑层
│ └── util/ # 工具函数
├── migrations/ # 数据库迁移文件
├── pkg/ # 可公共使用的库代码
├── scripts/ # 构建、安装等脚本
├── test/ # 测试相关代码
├── web/ # Web前端相关代码
├── .gitignore # Git忽略文件列表
├── LICENSE # 项目许可证
├── README.md # 项目说明文件
└── go.mod # Go模块定义文件
MVC传统架构
经典模型
┌───────────────┐ ┌────────────┐ ┌──────────────┐
│ Controller │◄─────►│ Service │◄─────►│ Repository │
└───────────────┘ └────────────┘ └──────────────┘
(view layer) (controller layer) (model layer)
目录结构
Controller + VO / Service + BO / Repository + entity
server
.
├── cmd # 执行目录
├── common # 通用包
├── configs # 配置参数变量
├── database # 数据库连接
├── go.mod
├── internal
│ ├── controller # 接口层
│ │ └── vo # VO(View Object)模型
│ ├── repository # 访问持久化层
│ │ └── entity # Entity 实体
│ ├── pkg # 内部库
│ └── service # 业务逻辑层
│ └── bo # BO(Business Object)模型
├── main.go # 主入口
├── pkg # 外部库
├── router # 路由系统
└── test # 测试目录
对于传统面向过程的贫血模型而言,MVC 架构更加注重业务逻辑的封装和处理。在这种模型中,重点是强调 Service 层的职责,而对于 BO(Business Object)层则相对较轻。
DDD架构
经典模型
目录结构
server
├── README.md # 项目文档
├── application # 业务调度层
│ ├── event # 微服务事件推送或订阅
│ │ ├── publish # 事件发布
│ │ └── subscribe # 事件订阅
│ └── service # 用于连接 Controller 和 Domain,进行三方接口调用等其他操作
├── domain # 领域服务层(领域逻辑和领域对象,主要的业务逻辑,采用充血模型)
│ ├── aggregate01 # Aggregate 聚合根目录
│ │ ├── entity # entity 实体、VO 值对象以及工厂模式(Factory)相关
│ │ ├── event # 事件实体以及与事件活动相关的业务逻辑代码
│ │ ├── repository # 持久化领域对象,通常仅包括仓储接口,仓储实现应放到基础架构层实现
│ │ └── service # 领域服务代码,一个领域服务是多个实体组合出来的一段业务逻辑
│ ├── aggregate02
│ └── ...
├── go.mod # 依赖文件
├── infrastructure # 基础设施层
│ ├── api # 第三方 API/SDK
│ ├── configs # 配置参数变量
│ ├── database # 初始化数据库
│ ├── mq # 消息队列连接和配置
│ ├── persistence # 数据持久化(Domain 层 repository 的具体实现,数据库 CRUD 操作)
│ └── pkg # 工具函数
│ ├── common # 与业务相关包
│ └── utils # 公共基础包
├── interfaces # 接口层
│ ├── assembler # 实现 DTO 数据传输对象与 Domain Entity 之间的相互转换和数据交换,从表示层(Presentation Layer)向领域层(Domain Layer)进行数据传递
│ ├── controller # 控制器路由函数
│ └── dto/vo # 可包含多个领域对象的属性:DTO(Data Transfer Object)主要关注数据的传输,通常用于面向服务或接口设计,用于在系统的不同部分之间传递数据。VO(View Object)则更常用于用户界面 UI 层,用于呈现数据给用户
└── main.go # 主入口
在 DDD (领域驱动设计) 中,需要将重点放在领域层(Domain Layer)进行业务逻辑和规则的实现。服务层(Service Layer)主要负责协调和调度各个领域对象之间的交互。
简单来说,对于面向对象充血模型的 DDD 而言,是重 Domain 轻 Service!
架构图
基本概念
在 DDD 的世界中,涉及到了很多概念,包括但不限于以下内容:
- 统一语言
- 限界上下文
- 领域、子域、支撑域
- 聚合、实体、值对象
- 接口层、应用层、领域层、基础设施层
- 贫血模型、充血模型
总结
本文主要介绍了go项目一般目录结构、MVC目录结构、DDD目录结构,每种架构都有使用场景,作为开发者,需要深入理解各个架构的优缺点,根据自身项目规模、复杂度选择合适的架构。