Gin项目结构示例
最近写了一个gin项目,将整个结构简单总结了一下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
gin-el on master
❯ tree
文件夹 PATH 列表
卷序列号为 CAF6-B649
D:.
├─common // 通用内容数据库、jwt等
├─config // 配置文件
├─controller // controller请求先转成vo
├─middleware // 中间件jwt、log等中间件
├─model // model对应数据库表
├─repository // repo仓储层,对数据库直接CRUD
├─routes // 路由
├─service // service业务逻辑实现
├─utils
│ ├─errcode // 项目错误码
│ └─settings // 项目配置初始化操作封装
└─vo // view object,实现请求参数校验,后端响应的封装
|
client |
controller |
service |
repository |
model |
请求 |
|
|
|
|
—> |
转换成vo |
|
|
|
|
—> |
执行业务 |
|
|
|
|
—> |
CRUD |
|
|
|
|
<==> |
数据库表 |
|
|
<— |
CRUD结果 |
|
|
<— |
业务结果 |
|
|
<— |
封装成vo |
|
|
|
- controller接收client请求,将请求内容转换成request view object,同时完成请求参数的初步校验
- controller将校验完成的参数传递给service执行对应的业务逻辑
- service通过对repository层的CRUD操作再封装和整合实现对应的业务逻辑
- repository实现对数据库表model的CRUD
- 结果原路径返回,封装成response view object返回给client,避免直接暴露model
错误模块
业务错误代码应该和Http状态码要有所区分
,根据不同业务定义不同业务的error code
和error message
,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
type ErrCode int
// user
const (
errUser ErrCode = 2000 + iota
ERR_USER_NAME_USED
ERR_USER_MAIL_USED
...
)
var codeMsg = map[ErrCode]string{
// user
ERR_USER_NAME_USED: "用户名已被占用",
ERR_USER_MAIL_USED: "邮箱已被占用",
...
}
func GetErrMsg(code ErrCode) string {
return codeMsg[code]
}
|
- reposity仓储层出参仍然携带
error
- service业务逻辑层才对仓储层返回error处理,转换成对应的
ErrCode
- controller层最终返回的json数据附加上业务信息
ErrCode
和ErrMsg
示例
User Controller层,接收、响应请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
// User Controller
type UserController struct {
Service service.UserService
}
func NewUserController() UserController {
return UserController{Service: service.NewUserService()}
}
func (u UserController) Register(ctx *gin.Context) {
// 请求转换成vo
...
// 创建用户
...
// 带外键信息返回
...
// 发放token
...
// response vo并响应
userResponse := vo.ToUserResponse(user)
ctx.JSON(http.StatusOK, gin.H{
"status": code,
"msg": errcode.GetErrMsg(code),
"user": userResponse,
"token": token,
})
}
|
User Service层,通过再封装和整合repo层的CRUD操作实现业务逻辑,但不直接操作数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// User Service
type UserService struct {
UserRepo repository.UserRepo
GroupRepo repository.UserGroupRepo
}
func NewUserService() UserService {
return UserService{
UserRepo: repository.NewUserRepo(),
GroupRepo: repository.NewUserGroupRepo(),
}
}
func (u UserService) Register(name, mail, password string, groupId uint) (*model.User, errcode.ErrCode) {
// 检查用户分组
...
// 用户信息唯一性检查
...
// 创建用户
...
// 返回用户信息
...
return user, errcode.OK
}
|
User Repo 仓储层,直接操作数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// User Repo
type UserRepo struct {
db *gorm.DB
}
func NewUserRepo() UserRepo {
db := common.GetDB()
db.AutoMigrate(model.User{})
return UserRepo{db: db}
}
func (u UserRepo) Create(name, mail, password string, userGroupId uint) (*model.User, error) {
...
}
func (u UserRepo) Delete() error {
...
}
func (u UserRepo) Find(id uint) (*model.User, error) {
...
}
func (u UserRepo) Update() (*model.User, error) {
...
}
|
gin项目结构示例