# 4.1 整体架构概览 :::tip 概述 系统采用分层架构 + 声明式基座 + 全局钩子横切 + gmeta 反射注解的组合。本节给出总架构图、模块依赖方向(允许/禁止)与启动编排,是理解全部机制的地图。 ::: ## 系统总架构图 ```text ┌───────────────────────────── 客户端 ─────────────────────────────┐ │ ui/(Vue3 + Element Plus,baseURL=/api) 其他 API 消费方 │ └──────────────────────────────────┬─────────────────────────────────┘ │ HTTP(Bearer JWT) ╔══════════════════════════════════▼═════════════════════════════════╗ ║ ghttp Server(:8000) ║ ║ ┌────────────────── 中间件链(顺序执行)──────────────────┐ ║ ║ │ CORS → Response → RateLimit → Demo → JWT → Tenant │ ║ ║ │ → OperationLog │ ║ ║ └──────────────────────────┬──────────────────────────────┘ ║ ║ ┌──────────────────────────▼──────────────────────────────┐ ║ ║ │ Bind 反射包装层(gmeta):权限校验 → 参数解析 → 分发 │ ║ ║ │ 路由元数据表 meta(权限/日志 注解即事实,补注册 goai) │ ║ ║ └──────────────────────────┬──────────────────────────────┘ ║ ║ controller(薄)→ service 接口(手维护)→ logic(ModuleSpec 基座) ║ ║ │ 侧路:utility/{jwt,captcha,cache,upload,excel,ip2region…} ║ ║ │ 侧路:gcron 调度器(job daemon + CleanTemp) ║ ║ ┌────▼─────────────────────────────────────────────────────┐ ║ ║ │ dao.Xxx.Ctx(ctx) —— 唯一查询入口 │ ║ ║ │ hooks.ApplyCtx:del_flag=0 + 租户级表 tenant_id IN(0,x) │ ║ ║ │ hooks.Handler:Insert 盖章 / Update 盖章 / Delete→软删 │ ║ ║ └────┬─────────────────────────────────────────────────────┘ ║ ╚══════╪══════════════════════════════════════════════════════════════╝ │ gdb(五驱动运行时切换) ┌──────▼────────┐ ┌──────────────┐ ┌─────────────────────────────┐ │ MySQL/PgSQL/… │ │ Redis(缓存) │ │ 磁盘 resource/upload + xdb │ └───────────────┘ └──────────────┘ └─────────────────────────────┘ ``` ## 模块依赖方向图(允许 / 禁止) ```text api/v1 ◀── controller ◀── logic ──▶ service(接口注册) │ ├──▶ dao ──▶ model/entity · model/hooks ──▶ gdb ├──▶ utility/*(无业务依赖) └──▶ consts internal/task ──▶ internal/logic ✅ 允许(任务复用 base 能力) internal/logic ──▶ internal/task ❌ 禁止(反向依赖) internal/middleware ──▶ 业务包 ❌ 禁止(经 wire.go 函数变量接线) internal/migrate ──▶ dao/logic ❌ 禁止(gdb 裸连,隔离钩子) base.go ──▶ 模块文件 ❌ 禁止(只依赖 dao/utility/consts) ``` ## 启动编排(internal/cmd) ```text main.go(注册五数据库驱动 + Redis 适配器 + blank import internal/logic) └─ internal/cmd.Run(ctx) ├─ 1) utility/cache.Init Redis 探测,失败降级进程内存 ├─ 2) wireDependencies 校验中间件依赖是否已由业务包 init 接线 ├─ 3) g.Server("easygoadmin") + router.Register(s) │ 中间件链注册 + 404/500 状态处理器 + SetServerRoot("resource") │ + /api/health + /swagger → 逐个 Bind 全部控制器 ├─ 4) go DaemonInit(延时 2s) 定时任务调度器加载 status=1 任务 ├─ 5) gcron 注册 CleanTemp 每日 03:30 清理上传临时目录 └─ 6) s.Run() 阻塞运行 HTTP 服务 ``` 延时 2s 的原因:等 HTTP 监听就绪(任务可能是 HTTP 调自身接口)。 ## 业务调用链(标准 CRUD) ```text Bind 包装(gmeta 权限/日志元数据) → controller.CXxx(薄层,仅转发 service.Xxx()) → service.IXxx 接口(internal/service/{模块}.go,手维护) → logic.sXxx 实现(internal/logic/{模块}.go,ModuleSpec 基座或手写) → dao.Xxx.Ctx(ctx)(唯一查询入口:挂全局钩子 + 注入 del_flag/租户条件) → gdb → 数据库 ``` ## 五个关键设计决策 | 决策 | 理由 | |------|------| | **目录平铺**:api/controller/logic/service 均单包,每模块一文件 | 跨模块直接同包调用(如 user 调 ResolveCityNames 无需 import);生成器目标路径唯一 | | **service 接口手维护** | 接口即文档;禁止 gf gen service 整体覆盖 | | **logic 同包 init() 注册** | 无需 blank import,包内全量加载 | | **中间件不依赖业务层** | IdentityLoader/TenantLoader/LogSink 以函数变量接线(wire.go),cmd 启动期检查告警 | | **dao.Ctx 唯一查询入口** | 软删/租户/审计三条红线在钩子层强制执行,业务零感知 | ## 分层职责速查 | 层 | 位置 | 职责 | 禁止 | |----|------|------|------| | api/v1 | api/v1/{模块}.go | 请求响应结构体 + gmeta 注解 | 业务逻辑 | | controller | internal/controller/{模块}.go | 薄层透传 | 业务/dao/手写响应 | | service | internal/service/{模块}.go | 接口契约(手维护) | 实现 | | logic | internal/logic/{模块}.go | 业务实现(基座+钩子+手写) | 反向依赖 task | | dao | internal/dao/ | 查询入口(钩子+红线条件) | 绕过直连 DB | | hooks | internal/model/hooks/ | 审计盖章/软删/租户 | 业务判断 |