# 统一 Go 后端(模块化单体) > 两个 PHP 后端(教务 ysw-finance + 教学 yuansiweimarking_v2)收敛为**一个 Go 后端**,模块化单体、单二进制(ADR-011)。本文档描述工程结构与域分包约定;架构决策见 `../unified/00-planning/用户系统合并规划.md`。 ## 定位 单一 Go 服务承载全部业务域:身份/SSO、多租户组织、教务域、教学域、AI 编排、异步任务。对外经 **nginx 统一入口**(TLS + HTTP/2 终结,ADR-010)暴露;数据库为 **PolarDB MySQL 单 schema**(ADR-008)。 ## 技术栈(与规划对齐) | 关注点 | 选型 | 依据 | |---|---|---| | 语言 | Go 1.27(go.mod 最低版本锁定;2026-11-05 由 1.23 升级,依赖零变化全绿实证) | 统一后端重写 | | Web 框架 | **Fiber** | ADR-009(用户拍板) | | ORM / 数据访问 | GORM + **Repository(强制作用域注入)** | ADR-006/007(多租户 institution/campus 过滤,应用层强制) | | 数据库 | PolarDB MySQL 单 schema | ADR-008(源库在阿里云,DTS 迁移) | | 身份 / SSO | OIDC(RS256),**identity 模块 = Provider + client 一体** | ADR-004 / ADR-011 | | 角色 | **7 类**:超管/教务/财务/老师/学生/家长/市场 | 三项拍板(市场扩入第 7 角色) | | 异步任务 | 统一 DB 任务表 + Go 工作池 | 替代两套旧队列 | | 配置 / 日志 | viper + zap | | | 外部入口 | nginx 统一七层入口(`proxy_buffering off` 支持 SSE) | ADR-010 | | 对象存储 | 阿里云 OSS | 文件资产迁移 | | AI 能力 | 消费 Python FastAPI Agent(契约 OpenAPI 化) | 跨系统综合分析 | ## 目录结构约定 ``` backend/ ├── README.md ← 本文件 ├── EXAMPLES.md ← 可编译样例索引 + GoDoc 注释标准(铁律 11 的落地模板) ├── go.mod ← Go 模块(go 1.27;依赖版本锁定,见"构建与校验") ├── cmd/api/ # 单二进制入口:装配 Fiber app + 各域模块 + 任务工作池(规划待建) ├── config/ # viper 配置:环境、多租户、DB/Redis/OSS、SSO 签发/验签(config.{env}.json 模板) └── internal/ ├── identity/ # 身份与 SSO(已有样例:id 生成 ULID / credential argon2 惰性升级 / token RS256 签发验签吊销) ├── org/ # 多租户组织:Institution / Campus / Membership / Role(7) / GuardianLink(规划待建) ├── academic/ # 教务域:排班 / 费用 / 打卡 / 充值(SP 重写) / 报课 / 同步(规划待建) ├── teaching/ # 教学域:备课 / 练习分析 / 题库 / 组卷 / 科目分表 / 共享标志(规划待建) ├── ai/ # AI 能力编排:作为 OpenAPI 消费方调用 Python Agent(规划待建) ├── task/ # 统一 DB 任务表 + 工作池(已有样例:t_task 状态机/乐观锁认领/指数退避) └── infra/ # 横切(已有样例:response 统一信封 / errors 三层错误 / scope 多租户作用域 / validator 入参校验 / config 12-factor 配置) ``` > **样例即规范**:`internal/infra/*`、`internal/identity/{id,credential,token}`、`internal/task` 为**可编译参考样例** > (`go build ./...` + `go vet ./...` 全绿,基于真实依赖版本),每个结构体/函数/方法均带 > GoDoc 中文注释(功能说明+典型样例、入参逐项、出参逐项+异常场景)。**新增业务域代码须对齐此注释标准**(铁律 11)。 > 样例索引与注释模板见 [EXAMPLES.md](./EXAMPLES.md)。 ## 分包铁律 1. **域间不直接互调内部实现**,跨域走 `internal/` 内定义的接口(接口在 `org`/`identity` 侧,消费方在业务域)。 2. **所有数据访问必须经 Repository 层**,作用域(institution_id / campus_id)由中间件从 token 解析后强制注入,禁止绕过。 3. **`infra` 不依赖任何业务域**;业务域可依赖 `infra`、`org`、`identity`,但 `org`/`identity` 不得反向依赖业务域。 4. **SP 行为(充值/审批/同步)在 `academic` 域内用 Go 事务重写**,旧存储过程仅留档对照,不迁移(见统一规划风险登记册)。 5. **硬编码身份/魔法值(如 `user->id==393`、`teacherId=354`)一律进配置或权限判断**,阶段 0 硬编码 ID 清单为消灭目标。 6. **统一响应契约**:HTTP 恒 200,真实状态码在 body `R.code`(成功 code=200,`{code,data,message}` 信封);e2e 断言 body code 而非 HTTP status(源自教务 Go 重构在产验证,ADR 见统一规划)。 7. **入参校验惯例**:`validateReq(c, req) bool`——校验失败内部已写 400 并返 false,调用方 `if !validateReq { return nil }`(用 `err!=nil` 判会误判通过继续落库)。 8. **路由注册顺序纪律**:Fiber 字面路径先于 `/:id`(如 `/courses/list-detail` 先于 `/courses/:id`);同 method+path 不重复注册(先注册优先);新增端点全局 grep 同路径。 9. **GORM 纪律**:`IS_NULLABLE=YES` 列一律 `*string`/`*int`(写边界 nil→""/0 归一);聚合/别名/无下划线列显式 `gorm:"column:xxx"`;链式调用勿就地改接收者(三查各自 `Model()`);事务内全部用 tx;service 返回 sentinel 错误(非 `gorm.ErrRecordNotFound`),handler 用 `errors.Is`。 10. **e2e id 段独立**:TestMain 建库建 SP→跑→DROP;多 e2e 共用库时用独立业务键/独立 id 段/独占时间窗/专属 token(避开教务已占 97090/97481/98141)。 11. **注释标准(GoDoc 三段式)**:每个导出的结构体/函数/方法/常量/错误**必须**带 GoDoc 中文注释,含①功能说明(用途+核心逻辑,导出项附"典型使用样例")②入参说明(逐项:名称、类型、含义、约束)③出参说明(逐项:名称、类型、含义;异常场景单列)。代码即文档——注释与实现必须一致,改实现同步改注释;索引与模板见 [EXAMPLES.md](./EXAMPLES.md)。 ## 构建与校验 ```bash # go.mod `go 1.27`(语言级别 + 最低工具链),本机 go 1.27.x 直接构建。 # 未写 toolchain 指令:旧机器(GOTOOLCHAIN=auto)会自动从 goproxy.cn 拉取 go1.27 工具链, # 有网即可,离线/内网隔离环境需预装 1.27 或设 GOPROXY 可达。 go build ./... # 0 错误 go vet ./... # 0 告警(1.27 起 go vet/go test 默认含 stdversion 检查:只用 ≤ go.mod 版本的标准库符号,天然满足) ``` **依赖版本锁定**(`go.mod`,升 go 1.27 后版本不变,已实测无意外升级): `fiber/v2 v2.52.16` / `gorm v1.31.2` / `validator/v10 v10.27.0` / `golang-jwt/jwt/v5 v5.3.1` / `oklog/ulid v1.3.1` / `x/crypto v0.33.0`。 > **工具链沿革**:初版锁 go 1.23 + validator v10.27.0(go 1.20 要求),防 tidy 把工具链抬到 1.26; > 2026-11-05 工具链升级为 **go 1.27**(泛型方法/encoding-json-v2/小对象分配提速 ~30%/goroutine 泄漏检测 GA), > 依赖保持原锁定版本,`go build`+`go vet` 全绿实证兼容。 ## 与文档目录的关系 - 本目录**只放代码与工程配置**;任何架构决策、数据模型、迁移/割接方案放 `../unified/`;单项目事实画像放 `../academic/`、`../teaching/`。 - 代码内注释如需引用决策,用相对路径指向 `../unified/00-planning/用户系统合并规划.md`,不在代码注释里复述结论。