后端 HTTP, RPC 服务通用架构,采用 go-clean-arch
The main point of clean architecture is: no matter your library, your architecture is clean, testable and independent
架构设计
Model层:用来存放接口的实现以及一些相关的结构体struct
Delivery层:暴露接口给外部调用,该层主要目的是请求参数校验和 response 的结果返回,不处理任何业务逻辑
UseCase层:纯用来处理业务逻辑
Repository层:只用操作数据库,执行数据库的增删改查;或者调用微服务
依赖关系就是:delivery 层依赖 usecase 层, usecase 层依赖 repository 层
对各个层进行的单元测试可以对接口使用 mockery工具 进行 mock 测试
我们在 go-clean-arch 的基础上,稍加改进形成下面的代码工程架构
除去系统自带的目录和文件,比如下面的
config
build.sh
go.mod
go.sum
README.md
我们自己的业务代码使用下面这种目录命名,也是分为三层
main.go main文件暴露在最外层
app 该目录存放相关的配置和结构体定义代码
handler.go 暴露给 main 函数调用我们的业务代码,handler.go 中的内容只能 main 函数调用
- domain 存放数据库相关的结构体定义信息
model.go 定义DB操作的相关的结构体,只存放DB相关的结构体的定义
types.go 定义需要使用的一体基本数据类型,比如枚举类型
constant.go 定义常量,比如表的名称,字段的名称
- config 存放读取配置相关的代码,比如数据库,消息队列的配置,以及初始化数据库client等的代码
client 连接数据库的代码,读取TCC的配置的代码
mongo.go 连接mongo的client
mysql.go 连接MySQL的client
rocketmq.go 连接RocketMQ的client
config.go 这里存放需要读取的相关配置项,比如MySQL的配置,mongo的配置,消息队列的配置
- interfaces
interface.go 定义pkg里面的所有的接口相关文件,这里的名字不一定要叫 interface.go
...
- mocks 存放上面接口mock出的代码,用于单元测试
pkg 该目录存放我们具体的代码逻辑相关文件,注意这个依赖关系, delivery->usecase->reposiory
所以usecase层不能调用任何相关的delivery包中的代码, repository也不能调用前两层的代码
- delivery 存放 delivery 层相关代码
a_handle.go
b_handle.go
helper.go 存放一些只能该目录需要使用的常量,以及一些结构体复制或者判断的小功能函数
- usecase 存放 usecase 层代码
a_usecase.go
b_usecase.go
helper.go 每层都可以有一个 helper.go 函数
- repository 存放 repository 层代码,这个repository应该是针对表的,理论上一个表一个 repository
student.go 代表 表`student` 相关的增删改查
teacher.go 代表 表`teacher` 相关的增删改查
helper.go
- myerror 自定义的error的处理代码
types.go 错误类型
student.go 关于`student`的错误类型
teacher.go 关于`teacher`的错误类型
- middleware 自定义的业务中间件
mdw.go 中间件定义
- utils 存放一些通用的小功能,比如参数转换(比如struct参数复制到response中),生成UUID等,字符串检验等
uuid.go 生成UUID
student.go 存放student相关的参数转换