这是我参与「第五届青训营 」笔记创作活动的第8天。
前言
青训营的大项目需要组队完成,因此我写的代码不能像以前一样只要自己看得懂就行了,必须要有清晰的架构以便团队协作。不然每个人的代码都跟狗皮膏药一样往上贴,项目就真成屎山了。
项目架构
参考了go-clean-arch和掘金视频课第四课的实现。
- repository层负责与数据库和其他微服务进行交互,根据usecase层的请求返回查询到的model。这个model就是GORM中的“M”,可以理解为数据表的一行数据。
- usecase层负责把查询到的model包装成entity。我个人的理解,entity就是借口文档里那些Video、User实体,但是由于一些原因无法直接用ORM存储到数据库里。比如说Video里面嵌套了一个User结构体用于记录用户信息,但是你数据库里不可能把User表嵌套进去,这样存储和更新的代价就太大了。所以只能记录user的id,usecase层根据视频id找video的model,然后根据里面的user id查到user的model,然后把两者组装一下返回。这一层不需要像另外两层一样做面向不同数据库、不同前端的各个模块,因为核心逻辑都是一样的;而且其输入输出也是固定的,是另外两层来适应它。
- delivery负责对接前端,接受前端发来的请求,调用usecase层,再把得到的entity包装成响应体返回。
- domain层定义了在其他三层里需要用到的各种结构体,即repository的Model、usecase层的Entity、delivery层的请求结构体与响应结构体;以及每一层要实现的接口。
文件结构
./src
|-- app //程序入口
| `-- main.go
|-- basic //对应大项目基础接口(视频、用户)
| |-- delivery //视图层
| | `-- http //web服务
| | |-- basic_handler.go //请求处理
| | `-- middleware //中间件,例如校验token
| | `-- middleware.go
| |-- repository //数据层
| | `-- mysql //与mysql交互
| | `-- mysql_basic.go
| `-- usecase //逻辑层
| `-- basic_usecase.go
|-- config.json //配置文件
|-- domain //各种结构体、接口的定义
| `-- basic.go
|-- go.mod
|-- go.sum
`-- public //存放静态文件
具体的文件结构如上所示。
- app中是程序的入口
- basic文件夹对应大项目三个模块之一,之后要写互动接口也再建一个文件夹。
- delivery为视图层
- http文件夹里实现了面向web前端的视图层函数(使用http协议)
- middleware里是中间件
- http文件夹里实现了面向web前端的视图层函数(使用http协议)
- repository为数据层
- mysql为与mysql数据库交互的部分
- usecae为逻辑层。这里不需要再建文件夹了,因为无论前端和数据库是啥,处理逻辑都一样。
- delivery为视图层
- public里存静态文件,比如说视频和封面等。
优点
- 可以轻松适配不同的数据库、前端,只需要编写repository或delivery层来对接即可。
- 可以很方便的替换各种框架,比如要把gin替换成hertz只需要改repository层;不想用gorm了也只需要改repository层。
- 便于协作,负责不同模块的同学只需要在src下新建自己模块的文件夹即可,不影响其他同学。
- 便于调试,核心的usecase层用go自带的test单元测试即可,repository层可以用mock测试,delivery层可以用框架自带的测试工具。