XYGo Admin 后端分层架构:Controller→Service→Logic→DAO 实战解析

XYGo Admin 后端分层架构:Controller → Service → Logic → DAO 实战解析

引言

在使用 GoFrame 开发中后台系统时,很多开发者会被一个问题困扰:代码到底该写在哪一层?Controller 里能不能写数据库查询?Logic 和 Service 有什么区别?DAO 是什么?这些困惑在团队协作中尤为突出------每个人有自己的"习惯写法",最终项目变成难以维护的"大泥球"。

XYGo Admin 作为一款基于 GoFrame + Vue3 的企业级中后台框架,提供了一套清晰的分层架构规范。本文通过实际代码示例,带你彻底理解这套分层设计,并掌握正确的开发姿势。

一、整体架构概览

XYGo Admin 的后端采用四层架构,请求处理流程如下:

```

HTTP Request

→ Middleware(鉴权、日志、响应包装)

→ Controller(参数校验、调用 Service)

→ Service(接口定义,自动生成)

→ Logic(业务逻辑实现)

→ DAO(数据库操作)

→ Database

```

每一层各司其职,职责边界非常清晰。下面逐层剖析。

二、Controller 层:只做"接"和"返"

Controller 是请求的入口,它的职责只有两件事:

  1. 接收并校验参数 :检查请求参数格式是否正确

  2. 调用 Service 并返回结果:不写任何业务逻辑

来看一个用户管理的 Controller 示例:

```go

// api/admin/user.go --- API 接口定义

type UserReq struct {

g.Meta `path:"/user/list" method:"GET" summary:"用户列表"`

Page int `json:"page" d:"1"`

PageSize int `json:"pageSize" d:"20"`

}

type UserRes struct {

List \[\]*userListVO `json:"list"`

Total int `json:"total"`

}

```

```go

// controller/admin/user.go --- 控制器

func (c *userController) List(ctx context.Context, req *v1.UserReq) (res *v1.UserRes, err error) {

return c.userService.List(ctx, req)

}

```

关键点:Controller 函数体只有一行,就是把参数传给 Service。如果你在 Controller 里写 `g.DB().Model("xy_user").Scan(...)`,那就破坏了架构。

三、Service 层:接口契约,自动生成

Service 层在 GoFrame 中是一个接口层,由 `gf gen service` 命令自动生成。开发者不需要手写它,相应的实现写在 Logic 中。

```go

// service/user.go --- 由 gf gen service 自动生成,不要手动修改

type IUser interface {

List(ctx context.Context, req *v1.UserReq) (res *v1.UserRes, err error)

}

```

这层的价值在于:接口与实现分离。Logic 层的实现只要满足这个接口,Controller 就不需要关心具体实现细节。后续替换实现(比如从 MySQL 迁到 TiDB),只需要改 Logic 层即可。

四、Logic 层:业务逻辑的核心战场

Logic 层是项目中最核心的代码层。所有业务逻辑都在这里实现。

```go

// logic/user/user.go

type sUser struct{}

func init() {

service.RegisterUser(New())

}

func New() *sUser {

return &sUser{}

}

func (s *sUser) List(ctx context.Context, req *v1.UserReq) (res *v1.UserRes, err error) {

// 分页查询

res = &v1.UserRes{}

err = dao.User.Ctx(ctx).

Page(req.Page, req.PageSize).

Scan(&res.List)

if err != nil {

return nil, err

}

count, err := dao.User.Ctx(ctx).Count()

if err != nil {

return nil, err

}

res.Total = count

return

}

```

Logic 层的优势在于:

  • 可测试性 :业务逻辑集中在一层,可以针对 Logic 编写单元测试

  • 可复用性 :多个 Controller 可以调用同一段 Logic 代码

  • 可维护性:业务变更时只需要修改 Logic 层的代码

五、DAO 层:数据库访问抽象

DAO(Data Access Object)是对数据库操作的封装,由 `gf gen dao` 命令自动生成。DAO 层位于 `internal/dao/` 目录下,而自动生成的内部实现则在 `dao/internal/` 中。

核心规则 :

  • `dao/internal/` 下的文件由 CLI 自动生成,不要手动修改

  • 扩展的查询方法写在 `dao/` 外层

```go

// dao/internal/user.go --- 自动生成,不要修改

type User struct {

Table string

Columns userColumns

}

type userColumns struct {

Id string

Username string

Password string

Nickname string

Email string

CreatedAt string

UpdatedAt string

}

```

当需要扩展自定义查询方法时,不在自动生成的文件里改,而是在外层扩展:

```go

// dao/user.go --- 自定义扩展方法

package dao

func (d *userDao) GetActiveUsers(ctx context.Context) (\[\]entity.User, error) {

return d.User.Ctx(ctx).

Where("status", 1).

Where("deleted_at", 0).

All()

}

```

六、实用开发建议

1. 使用 CRUD 生成器加速开发

XYGo Admin 内置了代码生成器,从数据表生成完整的前后端代码(包括 DAO、Entity、Logic、Controller 和 Vue 页面)。推荐开发流程是:

  1. 设计好数据库表结构

  2. 使用代码生成器生成初始代码

  3. 在 Logic 层补充业务逻辑

  4. 调整前端页面细节

这在大多数 CRUD 场景下,能节省 70% 以上的重复工作量。

2. 规范命名

  • Controller 文件:`controller/admin/模块名.go`

  • Logic 文件:`logic/模块名/模块名.go`

  • DAO 文件:`dao/表名.go`

3. 理解 Middleware 层

公共逻辑放在中间件,不要在 Controller 里重复处理。例如:

```go

// middleware/admin_auth.go --- 权限校验中间件

func AdminAuth(r *ghttp.Request) {

token := r.Cookie.Get("admin_token")

if token.IsEmpty() {

r.Response.WriteJson(g.Map{"code": 401, "msg": "未登录"})

r.Exit()

}

// 解析 token、获取用户信息、注入上下文

ctxUser := parseToken(token.String())

r.SetCtx(ghttp.PutCtx(r.Context(), "user", ctxUser))

r.Middleware.Next()

}

```

七、常见误区

| 误区 | 正确做法 |

|------|---------|

| Controller 里写 SQL 查询 | Controller 只做参数接收和返回,查询写在 Logic 层 |

| 手动修改 `dao/internal/` 文件 | 不要改,改完后下次 `gf gen dao` 会被覆盖 |

| 在 Logic 里直接调用另一个 Logic | 通过 Service 接口调用,保持层级清晰 |

| 手写 Service 接口 | Service 由 `gf gen service` 自动生成,手写容易不一致 |

总结

XYGo Admin 的四层架构设计,本质是约定大于配置的思想体现。每层都有明确的职责边界,开发者不需要纠结"这段代码放哪",按照规范写即可。这种分层带来的好处在大规模项目中尤为明显------代码可读性高、团队协作顺畅、重构成本低。

如果你是 GoFrame 新手,建议从 CRUD 生成器入手,先自动生成一套标准代码,然后逐层阅读生成的代码,感受清晰的分层结构。等熟悉之后再尝试手写业务板,你会发现自己已经自然而然地遵循了这套规范。

> 更多 XYGo Admin 开发文档和最佳实践,可参考官方网站。

相关推荐
天空属于哈夫克34 天前
企业微信二次开发:精准实现关键词自动回复
架构·企业微信
晨米酱4 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
这个DBA有点耶4 天前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
moMo4 天前
从固定流程到问题路由:让 LangGraph RAG 按需检索
架构
白远山4 天前
上海24小时自助健身房解决方案实战指南与经验分享
java·数据库·架构·需求分析
LorryJovens4 天前
【LAAP科研】双系统具身AGI范式研究——基于LAAP认知架构与Jev概率决策模型的系统性技术调研与范式验证
人工智能·gpt·安全·架构
JQweryuiop4 天前
中小型游戏陪练工作室数字化管理实践:基于七彩屋电竞护航小程序订单、履约与绩效系统的落地复盘
大数据·游戏·小程序·架构
LONGZETECH4 天前
一线职教实测:风光 580 汽车故障诊断仿真系统,破解实车实训四大核心痛点
人工智能·学习·安全·架构·汽车
萧瑟余晖4 天前
Netty 核心组件与 Reactor 模型详解
网络·架构