Files
Inbox/Go项目实战/通用上下文.md

961 lines
38 KiB
Markdown
Raw Permalink Normal View History

2025-12-11 07:24:36 +08:00
---
tags: []
aliases:
- Project Context Aggregation
date created: 星期三, 十二月 10日 2025, 12:10:59 凌晨
date modified: 星期三, 十二月 10日 2025, 12:06:29 中午
---
# Project Context Aggregation
> Source Items: 6
# ⚙️ Go 模块根路径约束 (Module Root Path Constraint)
**核心约束:**
- **项目 Go Module 路径 (Root Path):** `gitea-aliyun/Klein/enterprise-cms-core`
- **用途:** 所有内部导入Internal Imports必须以此路径作为前缀。
- **示例:**
- **错误:** `import "internal/pkg/ecode"`
- **正确:** `import "gitea-aliyun/Klein/enterprise-cms-core/internal/pkg/ecode"`
**AI 约束实施规则:**
1. 在生成任何包含 `import` 语句的代码时,必须检查并使用上述 Root Path。
2. 若代码位于 `internal` 目录下,且引用了另一个 `internal` 目录下的包,必须使用完整的 Root Path。
==== 00_ 软件产品全生命周期管理规范.md ====
```markdown
---
tags: []
aliases:
- 📘 软件产品全生命周期管理规范 (PDLC Guidelines)
date created: 星期日, 十二月 7日 2025, 12:49:19 下午
date modified: 星期日, 十二月 7日 2025, 12:49:54 下午
---
这是一个通用的、标准化的《互联网软件产品全生命周期PDLC管理规范》。此文档旨在为从灵感到交付的全过程提供顶层指导适用于中大型项目或追求工程卓越的小型团队。
---
# 📘 软件产品全生命周期管理规范 (PDLC Guidelines)
版本: 2.0 (通用标准版)
适用范围: 全栈开发、SaaS 产品、企业级应用系统
核心目标: 降低不确定性确保交付质量实现可预测的工程化产出。Shutterstock
---
## 阶段概览 (Phase Overview)
我们将产品落地过程划分为 7 个核心阶段P0 - P6。每个阶段都有明确的准入Entry和准出Exit标准。
|**阶段代号**|**阶段名称**|**核心角色**|**关键产出物**|
|---|---|---|---|
|**P0**|**立项与价值验证 (Inception)**|PM, Tech Lead, Stakeholder|BRD, 可行性分析报告|
|**P1**|**需求定义与原型 (Definition)**|PM, UI/UX|PRD, 原型图 (Figma)|
|**P2**|**技术方案设计 (Technical Design)**|Architect, Backend, Frontend|TDD, API 契约, ER 图|
|**P3**|**开发与实现 (Development)**|Developers|源代码, 单元测试|
|**P4**|**质量保障与验证 (Verification)**|QA, Developers|测试报告, Bug 清单|
|**P5**|**发布与部署 (Release)**|DevOps, Tech Lead|镜像, Release Note|
|**P6**|**运维与迭代 (Operations)**|SRE, Ops, PM|监控面板, 运营数据报告|
---
## 📅 详细阶段拆解
### P0: 立项与价值验证 (Inception & Strategy)
**目的:** 明确“为什么要做”。防止团队在伪需求或技术不可行的方向上浪费资源。
- **主要工作:**
1. **商业需求分析:** 确定业务痛点、目标用户及商业价值。
2. **技术可行性预研 (PoC):** 针对关键技术难点(如 AI 模型效果、高并发瓶颈)进行快速验证。
3. **资源评估:** 粗略估算所需人力、时间及服务器成本。
- **关键产出 (Artifacts):**
- `BRD (Business Requirement Document)`:商业需求文档。
- `PoC Demo`:概念验证原型(如有必要)。
- **决策门 (Gate):** **Go / No-Go**。如果 ROI投入产出比过低在此阶段终止。
### P1: 需求定义与产品设计 (Product Definition)
**目的:** 明确“要做成什么样”。将模糊的想法转化为具象的功能逻辑和视觉形态。
- **主要工作:**
1. **需求细化:** 编写详细的功能列表、用户故事 (User Stories) 和验收标准 (AC)。
2. **交互设计 (UX):** 绘制用户流程图 (User Flow)、低保真线框图。
3. **视觉设计 (UI):** 输出高保真设计稿、UI 切图、设计规范 (Design System)。
- **关键产出 (Artifacts):**
- `PRD (Product Requirement Document)`:产品需求规格说明书(唯一真理来源)。
- `Figma/Sketch Files`:高保真设计稿。
- **决策门 (Gate):** **需求评审 (PRD Review)**。开发团队确认需求逻辑闭环,无歧义。
### P2: 技术方案设计 (Technical Design)
**目的:** 明确“怎么实现”。**这是程序员最重要的规划阶段,严禁跳过此阶段直接编码。**
- **主要工作:**
1. **架构设计:** 确定微服务拆分、技术选型、中间件依赖Redis/MQ/DB
2. **数据建模 (Schema Design):** 绘制 ER 图,编写 DDL (SQL 建表语句),确定索引策略。
3. **接口定义 (API Contract):** 定义 URL、Method、Request/Response JSON 结构、错误码。
4. **详细设计 (TDD):** 核心算法逻辑、状态机流转图、时序图、缓存策略设计。
- **关键产出 (Artifacts):**
- `TDD (Technical Design Document)`:技术设计文档。
- `ER Diagram & SQL Scripts`:数据库模型与迁移脚本。
- `OpenAPI/Swagger Spec`API 接口定义文档。
- **决策门 (Gate):** **技术评审 (Design Review)**。架构师或 Tech Lead 确认方案具备扩展性、安全性及性能达标。
### P3: 开发与实现 (Implementation)
**目的:** 将设计转化为代码。注重代码质量与规范。
- **主要工作:**
1. **环境准备:** 本地开发环境搭建、Mock 数据生成。
2. **编码 (Coding):** 后端 API 开发、前端组件开发、业务逻辑实现。
3. **单元测试 (Unit Test):** 编写核心逻辑的单元测试,确保覆盖率。
4. **代码审查 (Code Review):** 提交 Merge Request进行同行评审。
- **关键产出 (Artifacts):**
- `Source Code`:符合规范的源码。
- `Unit Test Report`:单元测试通过报告。
- **决策门 (Gate):** **代码合并 (Merge)**。CI 流水线检查通过Lint, Test, Build
### P4: 质量保障与验证 (Quality Assurance)
**目的:** 确保交付物符合需求且无重大缺陷。
- **主要工作:**
1. **集成测试:** 前后端联调,确保接口数据交互正常。
2. **系统测试:** QA 团队根据测试用例进行全量测试。
3. **非功能测试:** 性能测试 (Load Test)、安全扫描 (Security Scan)。
4. **Bug 修复:** 开发修复 QA 发现的问题并回归。
- **关键产出 (Artifacts):**
- `Test Cases`:测试用例。
- `Bug List`:缺陷清单及修复记录。
- `Performance Report`:压测报告(可选)。
- **决策门 (Gate):** **验收评审 (UAT)**。Bug 清零或无 P0/P1 级 BugPM 验收通过。
### P5: 发布与部署 (Release & Deployment)
**目的:** 安全、平滑地将产品推向生产环境。
- **主要工作:**
1. **构建交付:** 编译二进制文件、构建 Docker 镜像。
2. **预发布验证 (Staging):** 在仿真环境中进行最后一次冒烟测试。
3. **正式部署 (Production):** 灰度发布 (Canary) 或 蓝绿部署,执行数据库迁移。
4. **回滚预案:** 准备好一旦失败的一键回滚脚本。
- **关键产出 (Artifacts):**
- `Release Note`:发布说明(变更日志)。
- `Docker Image / Binaries`:制品。
- **决策门 (Gate):** **上线检查清单 (Checklist)**。确认配置、密钥、数据库备份均已就绪。
### P6: 运维与持续迭代 (Operations & Maintenance)
**目的:** 保障系统稳定性,根据反馈进行优化。
- **主要工作:**
1. **监控告警:** 配置 CPU/内存、QPS、错误率监控设置 PagerDuty 告警。
2. **日志审计:** 收集与分析运行日志 (ELK/Loki)。
3. **数据复盘:** 分析用户行为数据,验证 P0 阶段的商业假设。
4. **事故复盘 (Post-mortem):** 若发生故障,撰写复盘报告,制定改进措施。
- **关键产出 (Artifacts):**
- `SLA Report`:服务可用性报告。
- `User Analytics`:用户数据分析报表。
---
## ⚙️ 关键支撑体系 (Supporting Pillars)
除了上述流程,以下三个支撑体系贯穿始终:
1. **项目管理 (Project Management):** 使用 Jira/Trello 管理任务看板,每日站会同步进度,识别风险。
2. **配置管理 (Configuration Management):** 代码版本控制 (Git Flow),环境配置隔离 (Env Vars)。
3. **文档工程 (Documentation):** 保持 BRD, PRD, API 文档与代码的同步更新,避免“文档腐烂”。
```
==== 关于个人开发者的开发模式.md ====
```markdown
---
tags: []
aliases:
- 渐进式开发最佳实践
date created: 星期一, 十二月 8日 2025, 12:04:31 凌晨
date modified: 星期一, 十二月 8日 2025, 12:05:12 凌晨
---
# 渐进式开发最佳实践
## 1. 必须在写代码前锁定的“硬约束” (The Non-Negotiables)
即使是后规划细节,但这 **4 样东西** 是一旦开工就很难改的,必须在骨架阶段定死:
1. **目录结构 (Directory Layout):** `cmd`, `internal`, `pkg` 怎么分。这决定了你能不能顺畅地加代码。
- _现状:_ 我们已经定好了 (Modular Clean Architecture)。
2. **核心技术栈与基础设施:** 选 Gin 还是 Echo用 GORM 还是 SQLX依赖注入用 Wire 还是手写。
- _现状:_ 我们已经定好了 (Gin+GORM+Wire+Viper)。
3. **统一的交互规范:** API 怎么返回错误?数据库怎么管理变更?日志打在哪里?
- _现状:_ 我们已经定好了 (JSON Envelope, Golang-Migrate, Zap)。
4. **核心领域模型 (Core Schema):** 最关键的表User, Role
- _原因:_ 它们是系统的地基,地基不稳,后面写 Service 逻辑会反复推倒重来。
---
## 2. 可以(且应该)推迟设计的“软逻辑” (The Deferrables)
这些内容不要现在想,想了也是白想,等写到那个函数时再具体的“具体问题具体分析”:
1. **复杂的业务算法:** 比如“文章的热度排名算法”、“复杂的权限递归校验逻辑”。
- _策略:_ 先写个 `return true` 或简单的逻辑占位,跑通流程再说。
2. **极致的性能优化:** 比如“这里要不要加 Redis 缓存?”、“这里 SQL 要不要分表?”。
- _策略:_ 先跑通功能 (Make it work),再优化性能 (Make it fast)。
3. **非核心字段的定义:** 比如文章表里要不要加 `seo_keywords`,用户表要不要加 `wechat_id`
- _策略:_ 用到了再加 migration不要为了“未来可能用到”而过度设计。
4. **具体的 API 参数细节:** 比如“更新文章是传 ID 还是传 UUID”。
- _策略:_ 写 Handler 的时候,顺手定义 DTO 就行。
---
## 3. 个人开发者的“曳光弹”开发流 (The Tracer Bullet Workflow)
不要试图“横向”开发(先把所有 50 张表设计完,再把所有 API 定义完)。
要进行 “纵向”切片开发Vertical Slice
**推荐的实操步骤:**
### 第一阶段:搭建“行走的骨架” (Day 1 - 也就是你现在该做的)
**目标:** 一个能跑起来、能连数据库、有日志、有 Swagger 文档,但没有任何业务功能的空壳。
1. **初始化项目:** 建立文件夹,`go mod init`
2. **配置基础设施:** 放入 `Makefile`, `docker-compose.yml`, `config.yaml`
3. **连通性测试:** 写一个简单的 `GET /ping` 接口,确保能读到配置,能连上 DB能打出日志。
4. **依赖注入跑通:** 确保 `wire` 能自动生成代码并启动 Server。
5. **结果:** 你拥有了一个**“生产级”的 Hello World**。
### 第二阶段:第一个“核心切片” (Day 2-3)
**目标:** 打通 User 模块的完整闭环。
1. **DB:** 设计 `users` 表,执行 Migrate。
2. **Entity:** 生成 User Struct。
3. **Repo:**`CreateUser``FindUser` 的 CRUD。
4. **Service:**`Register` 逻辑(这里涉及到密码加密,此时再去查 Argon2 怎么用)。
5. **API:** 定义 `RegisterReq` DTO写 Handler。
6. **测试:** 用 Postman/Swagger 调通注册接口。
### 第三阶段:具体问题具体分析 (Day 4+)
**目标:** 遇到什么写什么。
- _场景:_ 比如你做到了“文章发布”,突然发现需要“敏感词过滤”。
- _动作:_ 停下来,在 `pkg/util` 里设计一个敏感词过滤函数(或者找个库),然后在 Service 层调用它。
- _这就是你说的:_ “进行到具体的业务逻辑的时候进行设计”。
---
## 4. 总结给你的建议
你现在的焦虑在于试图**预见未来**。
**作为个人开发者,你的代码就是你的设计文档。**
**你的下一步行动:**
1. **停止**思考复杂的业务场景。
2. **立即**按照我们之前确定的目录结构,新建文件夹。
3. **立即**把 `docker-compose` 跑起来,把 `main.go` 跑起来。
4. **立即**实现“用户注册”这一个功能。
只要“骨架”(架构分层、依赖注入、数据库管理方式)是对的,后面你往里面填什么肉(业务逻辑),怎么填,都不会把楼盖歪。
**准备好开始初始化项目文件夹了吗?**
```
==== 关于项目的顶层设计模式和风格.md ====
```markdown
---
tags: []
aliases:
- 🏗️ Project Architecture & Design Guidelines (v1.0)
date created: 星期日, 十二月 7日 2025, 11:57:43 中午
date modified: 星期二, 十二月 9日 2025, 11:00:14 晚上
---
# 🏗️ Project Architecture & Design Guidelines (v1.0)
项目代号: Enterprise-CMS-Core
架构风格: 模块化整洁架构 (Modular Clean Architecture)
核心原则: 实用主义 (Pragmatic)、Go 原生思维 (Idiomatic)、领域驱动 (DDD-Lite)
## 1. 技术栈约束 (Tech Stack Constraints)
- **Language:** Go 1.21+
- **Web Framework:** Gin
- **Database:** PostgreSQL (Primary), Redis (Cache)
- **ORM:** GORM (With Migration Tools)
- **Dependency Injection:** Google Wire
- **Configuration:** Viper (YAML)
- **Observability:** Zap (Log), Prometheus (Metrics), Jaeger (Trace)
- **Documentation:** Swagger / OpenAPI 3.0
---
## 2. 目录结构规范 (Directory Structure)
采用 **“按领域分包 (Package by Domain)”** 的扁平化结构,而非传统的按层分包。
```Plaintext
root/
├── cmd/server/
│ ├── main.go # 仅包含 wire 初始化与 app.Run()
│ └── wire.go # 顶层依赖注入定义
├── config/ # 配置文件模板 (config.yaml)
├── internal/
│ ├── api/ # [API层] 全局通用的 HTTP DTO (Request/Response)
│ ├── middleware/ # [中间件] Gin 中间件 (Auth, CORS, Logger)
│ ├── pkg/ # [基础设施] 内部通用组件 (AppResult, ErrorCode)
│ │
│ │ # --- 核心业务领域 (Domain Modules) ---
│ │ # 每个领域包内部扁平化,自包含所有逻辑
│ ├── user/ # [示例] 用户领域
│ │ ├── entity.go # 核心实体 (GORM Model)
│ │ ├── repository.go # 仓储接口定义 + GORM 实现
│ │ ├── service.go # 业务逻辑 (Service Struct)
│ │ ├── handler.go # HTTP 控制器 (Controller)
│ │ └── provider.go # Wire ProviderSet
│ │
│ └── article/ # [示例] 文章领域 (结构同上)
├── pkg/ # [外部库] 可抽离的通用工具 (Hash, JWT, Logger封装)
├── migrations/ # 数据库迁移 SQL 文件 (up/down)
├── go.mod
└── Makefile
```
---
## 3. 核心架构设计规则 (Architectural Rules)
### 3.1. 依赖倒置与注入 (IoC & DI)
- **规则:** 严禁在业务代码中手动 `New()` 依赖对象。
- **实现:** 所有依赖关系必须通过 `NewStruct(dep Interface)` 构造函数声明,并由 `Google Wire` 在编译期自动组装。
- **模块化注入:** 每个领域包(如 `internal/user`)必须包含一个 `provider.go`,导出 `var ProviderSet = wire.NewSet(…)`,供顶层 `cmd/server/wire.go` 聚合。
### 3.2. 接口策略 (Interface Strategy)
- **Repository (必须):** 仓储层**必须**定义接口(例如 `UserRepository`),以支持 Mock 测试和数据库切换。
- **Service (按需):** 默认**不需要**定义 Service 接口,直接使用 Struct。仅在以下情况提取接口
1. 出现循环依赖。
2. 需要对 Service 进行 Mock 测试。
3. 该 Service 存在多种策略实现(如 `PaymentService` 有支付宝/微信两种实现)。
### 3.3. 领域包扁平化 (Flat Domain Package)
- **规则:** 在 `internal/user/` 等领域包内,**不再**建立 `service/`, `repo/` 子目录。
- **原因:** 利用 Go 的 `package` 级私有可见性,隐藏领域内部细节(如辅助函数、内部 DTO仅暴露必要的 Handler 和 Service 方法。
### 3.4. 数据模型 (Model Vs Entity)
- **策略:** 采用 **"Pragmatic Entity"** 模式。
- **定义:** `entity.go` 中的结构体既是业务实体,也是 GORM 模型(带 `gorm:"…"` 标签)。
- **例外:** 只有当数据库存储结构与业务逻辑结构差异巨大时,才在 Repository 内部引入独立的 PO (Persistent Object) 并进行转换。
---
## 4. 编码实施标准 (Implementation Standards)
### 4.1. 错误处理 (Error Handling)
- **禁止:** 严禁直接返回 `error` 字符串给前端。
- **必须:** Service 层返回标准 `error`Controller 层通过 `pkg/app` 将其转换为统一响应格式。
- **格式:**
```Go
// Response JSON
{
"code": 20001,
"msg": "User already exists",
"data": null
}
```
### 4.2. 数据库交互 (Database Interaction)
- **禁止:** Controller 层严禁导入 `gorm` 包,严禁执行 SQL。
- **迁移:** 生产环境严禁使用 `AutoMigrate`。必须使用 `migrations/` 目录下的版本化 SQL 脚本进行变更。
### 4.3. 路由注册 (Router Registration)
- **规则:** 路由不再集中管理。
- **实现:** 每个领域包暴露一个 `RegisterRoutes(r *gin.RouterGroup)` 方法。在 `main.go` 启动时,统一调用各模块的注册方法。
---
## 5. AI 编程指令 (Instruction for AI Agent)
> **当作为 AI 助手编写代码时,请严格遵守以下指令:**
1. **Context Check:** 在生成代码前,检查当前目录结构是否符合 `Section 2`。如果不符,请优先建议重构或遵循现有结构。
2. **No Logic Leak:** 确保 HTTP 处理逻辑(解析参数、校验参数)留在 `handler.go`,业务规则(判断权限、计算)留在 `service.go`SQL 操作留在 `repository.go`
3. **Wire Awareness:** 每当新增 Service 或 Repository必须自动更新同目录下的 `provider.go`,并在 `cmd/server/wire.go` 中检查是否需要重新生成。
4. **Testability:** 编写 Repository 代码时,优先考虑“如何 Mock”。
```bash
==== 规范数据库设计 & 变更管理及工程流操作.md ====
```markdown
---
tags: []
aliases:
- 🛠️ Database Engineering & Migration Standard (v1.0)
date created: 星期日, 十二月 7日 2025, 10:31:59 晚上
date modified: 星期二, 十二月 9日 2025, 10:14:44 晚上
---
# 🛠️ Database Engineering & Migration Standard (v1.0)
文档用途: 规范数据库设计、变更管理及工程流操作。
适用范围: 所有涉及 Schema 变更的后端开发任务。
核心原则: Code First (Logic) but SQL First (Schema). 严禁生产环境使用 ORM 自动建表。
---
## 1. 基础设施与工具链 (Infrastructure & Tools)
本项目采用 **“容器化数据库 + 版本化迁移工具”** 的架构。
| **组件** | **选型** | **说明** |
| --------------- | ------------------ | ----------------------------------------- |
| **Database** | **PostgreSQL 15+** | 运行于 Docker 容器中,保证开发/生产环境一致。 |
| **Schema Mgmt** | **Golang-Migrate** | CLI 工具,用于生成和执行版本化 SQL 脚本。 |
| **GUI Client** | **Navicat** | 推荐 Navicat / DataGrip / DBeaver仅用于设计和验证。 |
| **Automation** | **Make** | 封装常用命令,屏蔽底层复杂参数。 |
### 1.1 目录结构规范
Plaintext
```bash
project-root/
├── migrations/ # [Source of Truth] 存放所有 SQL 变更文件
│ ├── 000001_init_users.up.sql
│ └── 000001_init_users.down.sql
├── internal/
│ └── {domain}/ # 领域包
│ └── entity.go # [Code Mapping] GORM 结构体定义
├── docker-compose.yml # 定义本地 DB 容器
└── Makefile # 集成迁移命令
```
---
## 2. 数据库设计规范 (Design Standards)
### 2.1 命名约定
- **表名:** 必须使用**复数**形式,`snake_case` (e.g., `users`, `order_items`).
- **字段名:** 全小写,`snake_case` (e.g., `created_at`, `user_id`).
- **索引名:**
- 普通索引: `idx_tablename_column`
- 唯一索引: `uniq_tablename_column`
- **外键名:** `fk_tablename_ref_tablename`
### 2.2 关键字段约束
所有业务表**必须**包含以下基础字段:
```SQL
id BIGSERIAL PRIMARY KEY, -- 或 UUID
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ -- 仅在需要软删除时添加
```
### 2.3 设计禁忌
1. **严禁** 使用物理外键的级联删除 (`ON DELETE CASCADE`),除非是关联性极强的子表(如文章标签关联)。核心业务数据必须使用 `ON DELETE RESTRICT`
2. **严禁** 在涉及金额的字段使用 `FLOAT``DOUBLE`,必须使用 `DECIMAL``BIGINT` (分)。
3. **严禁**`NULL` 作为布尔值的第三种状态。布尔字段必须设置 `NOT NULL DEFAULT FALSE`
---
## 3. 标准作业流程 (SOP)
开发人员需严格遵循以下 **5 步闭环** 进行数据库变更:
### Step 1: 启动环境
确保本地 Docker 数据库正在运行。
```Bash
make network # 对应 docker-compose up -d
```
### Step 2: 创建迁移文件 (Create)
使用 Makefile 生成成对的 `.sql` 文件up/down
- `name` 参数应简短描述变更内容(如 `add_avatar_to_users`)。
```Bash
make new_migration name=init_schema
# 输出:
# Created migrations/000001_init_schema.up.sql
# Created migrations/000001_init_schema.down.sql
```
### Step 3: 编写 SQL (Edit)
- **UP 文件:** 填入 `CREATE TABLE`, `ALTER TABLE`, `CREATE INDEX` 等正向操作。
- _技巧:_ 可在 GUI 工具中设计好表结构,复制生成的 DDL 语句粘贴至此。
- **DOWN 文件:** 填入对应的回滚操作(如 `DROP TABLE`, `DROP INDEX`)。
### Step 4: 执行变更 (Apply)
将 SQL 应用到本地数据库。
```Bash
make migrate_up
```
_验证:_ 使用 GUI 工具连接数据库,确认表结构已更新。
### Step 5: 代码映射 (Mapping)
`internal/{domain}/entity.go` 中编写对应的 Go Struct。
- 确保 `gorm` tag 与数据库定义一致。
- 确保 `json` tag 符合 API 契约。
---
## 4. 自动化配置 (Automation)
将以下内容固化到项目根目录的 `Makefile` 中。
> **注意:** 确保 `DB_DSN` 与 `docker-compose.yml` 中的配置完全一致。
```Makefile
# ==============================================================================
# Database & Migration Logic
# ==============================================================================
# Database Connection String
# 格式: postgres://user:password@host:port/dbname?sslmode=disable
DB_DSN := postgres://postgres:secret@localhost:5432/cms_core?sslmode=disable
.PHONY: network new_migration migrate_up migrate_down migrate_force
# 1. 启动本地环境
network:
docker-compose up -d
# 2. 创建新的迁移文件 (Usage: make new_migration name=create_users)
new_migration:
@if [ -z "$(name)" ]; then echo "Error: name is required"; exit 1; fi
migrate create -ext sql -dir migrations -seq $(name)
# 3. 执行所有未执行的迁移 (Up)
migrate_up:
migrate -path migrations -database "$(DB_DSN)" up
# 4. 回滚上一次迁移 (Down 1 step)
migrate_down:
migrate -path migrations -database "$(DB_DSN)" down 1
# 5. 强制修复版本 (当 dirty database 时使用, version 为具体的版本号)
migrate_force:
migrate -path migrations -database "$(DB_DSN)" force $(version)
```
---
## 5. 故障排查 (Troubleshooting)
**Q: 执行 migrate_up 时报错 "Dirty database version x".**
- **原因:** 上一次迁移执行到一半失败了(可能是 SQL 语法错误),导致版本锁死。
- **解决:**
1. 手动修复 SQL 文件中的语法错误。
2. 执行 `make migrate_force version=x` (x 是失败前的那个版本号)。
3. 再次执行 `make migrate_up`
**Q: 多人协作时产生版本冲突。**
- **现象:** 你有一个 `0003_add_xx.up.sql`,同事提交代码后也有一个 `0003_add_yy.up.sql`
- **解决:** 重命名你的迁移文件编号为 `0004`,确保序列号在时间轴上是递增且唯一的。
```bash
==== 七七八八的接口设计相关问题.md ====
```markdown
---
tags: []
aliases:
- 1. 接口版本控制策略 (API Versioning Strategy)
date created: 星期日, 十二月 7日 2025, 11:38:52 晚上
date modified: 星期日, 十二月 7日 2025, 11:42:18 晚上
---
# 七七八八的接口设计相关问题
## 1. 接口版本控制策略 (API Versioning Strategy)
**核心问题:** 当你发布了 V1 版本后,某天需要修改接口字段(比如把 `name` 拆分为 `first_name``last_name`),如何保证老版本的 App 不会崩溃?
**三种主流流派:**
1. **URI Path Versioning (推荐):**
- **格式:** `https://api.example.com/v1/users`
- **优点:** 直观、易于调试、缓存友好。这也是 GitHub, Twitter, Google API 采用的主流方案。
- **落地:** 我们在 Gin 的 Router Group 中直接体现:
Go
```bash
v1 := r.Group("/api/v1")
{
v1.GET("/users", ...)
}
```
2. **Header Versioning:**
- **格式:** Header 中添加 `Accept: application/vnd.myapi.v1+json`
- **优点:** URL 干净。
- **缺点:** 调试麻烦(浏览器直接访问 URL 看不到结果CDN 缓存配置复杂。**不推荐 MVP 阶段使用。**
3. **Query Parameter:**
- **格式:** `/users?version=1`
- **评价:** 看起来很土,通常不用于 RESTful API。
**👉 你的策略:** 坚定选择 **URI Path Versioning (`/api/v1`)**。只在发生**破坏性变更 (Breaking Change)** 时才升级到 v2。新增字段不算破坏性变更不需要升级版本。
---
## 2. HTTP 方法的精准语义 (Verbs Semantics)
很多新手只会用 `GET``POST`。企业级 API 必须精准区分以下方法的含义:
|**方法**|**语义**|**幂等性 (Idempotency)**|**典型场景**|
|---|---|---|---|
|**GET**|获取资源|✅ 是|获取文章列表、详情|
|**POST**|新建资源|❌ 否|发布新文章、提交评论|
|**PUT**|**全量替换**资源|✅ 是|修改文章(客户端发送文章的完整 JSON没传的字段会被置空|
|**PATCH**|**局部更新**资源|❌ 否 (理论上)|修改文章状态(只传 `{"status": "published"}`,其他字段不变)|
|**DELETE**|删除资源|✅ 是|删除文章|
⚠️ 重点关注 PUT vs PATCH:
在 Go 语言中实现 PATCH 有点麻烦(因为 Go 的结构体默认值问题,你很难区分用户是传了 0 还是没传这个字段)。
- **最佳实践:** 对于 CMS 这种表单复杂的系统,**修改接口首选 `PUT` (全量)**,或者针对特定状态修改提供独立接口(如 `POST /articles/:id/publish`)。如果必须做 `PATCH`DTO 需使用指针类型 `*string` 来判断是否为 `nil`
---
## 3. RESTful URL 设计模式 (Resource Naming)
**原则URL 中只出现名词,不出现动词。**
-**反例 (RPC 风格 - 不要这么做):**
- `/api/getUsers`
- `/api/createUser`
- `/api/deleteArticle?id=1`
-**正例 (REST 风格):**
- `GET /api/v1/users` (获取列表)
- `POST /api/v1/users` (创建)
- `DELETE /api/v1/articles/1` (删除 ID 为 1 的文章)
**复杂关系的嵌套设计:**
- _场景:_ 获取某篇文章下的评论。
- _设计:_ `GET /api/v1/articles/{article_id}/comments`
- _场景:_ 获取某个作者的所有文章。
- _设计:_ `GET /api/v1/users/{user_id}/articles`
---
## 4. 列表接口三剑客:分页、排序、筛选 (Pagination, Sorting, Filtering)
你的 CMS 一定会有“文章列表”页面,这个接口是最复杂的。不要为每种查询都写一个新接口,要设计一个**通用的查询接口**。
**最佳实践标准:**
1. **分页 (Pagination):**
- 使用 `page` (页码) 和 `page_size` (每页条数)。
- URL 示例: `/articles?page=2&page_size=20`
- **注意:** 要限制 `page_size` 的最大值(如 100防止恶意用户一次请求 100 万条数据把数据库打挂。
2. **排序 (Sorting):**
- 使用 `sort` 参数。`-` 代表降序,无符号代表升序。
- URL 示例: `/articles?sort=-created_at` (按创建时间倒序)
- URL 示例: `/articles?sort=view_count,-created_at` (先按浏览量升序,再按时间倒序)
3. **筛选 (Filtering):**
- 直接使用字段名作为参数。
- URL 示例: `/articles?category_id=1&status=published`
---
## 5. 状态码与错误处理 (Status Codes & Error Handling)
**不要永远只返回 200 OK**
前端开发最恨的就是HTTP 状态码是 200结果 Body 里写着 `{"code": 500, "msg": "Error"}`。这会让监控系统失效。
**你需要遵守的“HTTP 状态码地图”:**
- **2xx (成功):**
- `200 OK`: 通用成功。
- `201 Created`: 创建成功 (POST 返回)。
- `204 No Content`: 删除成功 (DELETE 返回,不带 Body)。
- **4xx (客户端错误 - 前端背锅):**
- `400 Bad Request`: 参数校验失败(如邮箱格式不对)。
- `401 Unauthorized`: 未登录/Token 过期。
- `403 Forbidden`: 登录了,但没权限(如普通用户想删文章)。
- `404 Not Found`: 资源不存在。
- **5xx (服务端错误 - 你背锅):**
- `500 Internal Server Error`: 代码崩了/数据库挂了。
统一错误响应格式 (JSON Envelope):
无论发生什么错误Body 必须保持结构一致,方便前端拦截:
JSON
```bash
{
"code": 40001, // 业务错误码 (你在 pkg/e 定义的)
"message": "标题已存在", // 给用户看的提示
"request_id": "abc-123" // 方便查日志的 Trace ID
}
```
---
## 6. 进阶知识:幂等性 (Idempotency)
**概念:** 用户因为网络卡顿,连续点击了 3 次“发布文章”按钮,你的系统会创建 1 篇文章还是 3 篇?
- **非幂等:** `POST`。点 3 次创建 3 篇。
- **幂等:** `PUT` / `DELETE`。改 3 次和改 1 次结果一样;删 3 次和删 1 次结果一样(都是没了)。
如何处理 POST 的幂等性?
对于关键业务(如支付、核心数据创建),通常要求前端在 Header 带一个 Idempotency-Key (UUID)。后端 Redis 记录这个 Key如果短时间内收到相同的 Key直接返回上次的结果不执行数据库插入。
(注MVP 阶段可以先不做,但面试或者做高可靠系统时必须知道)
---
## 总结:在你开始定义 API 之前
请在心中建立这套标准:
1. **URL:** `/api/v1/名词`
2. **Method:** 查询用 GET新建用 POST修改用 PUT删除用 DELETE。
3. **List:** 永远记得预留 `page`, `page_size`
4. **Response:** 永远返回统一的 JSON 结构,报错必须用 4xx/5xx 状态码。
**准备好了吗?我们可以开始基于这些原则,设计 User 模块的 API 了。**
```bash
==== 产品需求规格说明书 (PRD) - V1.1.md ====
```markdown
---
tags: []
aliases:
- 📝 产品需求规格说明书 (PRD) - V1.1
date created: 星期日, 十二月 7日 2025, 12:14:41 中午
date modified: 星期日, 十二月 7日 2025, 12:49:19 下午
---
# 📝 产品需求规格说明书 (PRD) - V1.1
> **更新日志:**
>
> - v1.0: 初始版本,定义功能列表。
>
> - **v1.1:** [2025-12-07] 补充项目战略背景;优化软删除与缓存策略的灵活性;明确长文本存储类型。
项目名称: Enterprise-CMS-Core (企业级内容管理系统核心)
版本: 1.1.0
状态: [✅ 已锁定]
适用对象: 后端开发人员、架构师、测试人员
---
## 1. 项目战略概述 (Strategic Overview)
### 1.1 项目背景与目标
本项目并非单纯为了交付一个 CMS 软件,而是为了构建一个**“Go 语言企业级后端架构样板间”**。
- **核心目标:** 验证并固化一套“模块化整洁架构”工程实践,使其具备**高可维护性**、**可扩展性**和**安全性**。
- **衍生价值:** 产出的源码将作为团队未来的“SaaS 启动脚手架 (Boilerplate)”,或作为独立的高价值技术资产(源码付费产品)进行商业变现。
### 1.2 核心用户与价值
- **系统管理员 (Admin):** 痛点是“安全与失控风险”。核心价值是提供**银行级的 RBAC 权限控制**,确保没人能越权操作。
- **内容编辑 (Editor):** 痛点是“流程混乱”。核心价值是提供**状态明确的内容流转机制**(草稿 ->审核 ->发布),防止误发。
- **二开开发者 (Developer):** 痛点是“屎山代码”。核心价值是提供**清晰的依赖边界**和**开箱即用的基础设施**。
### 1.3 成功指标 (Success Metrics)
1. **业务完整性:** 必须完整支持 3 种标准角色Admin/Editor/Subscriber的权限隔离且文章状态流转无逻辑漏洞。
2. **工程质量:** 核心业务模块User/Auth单元测试覆盖率 > 80%;通过静态代码分析,无循环依赖。
3. **性能基线:** 在单机 2C4G 配置下,并发 100 QPS 时API P99 响应时间 < 200ms
---
## 2. 核心功能范围 (In-Scope)
### 2.1 认证与鉴权模块 (Auth & IAM)
**唯一来源:** 必须使用 JWT 双令牌机制 + RBAC 模型。
- **F-AUTH-01 用户注册:** 仅支持“用户名 + 密码”注册。密码必须经过 Argon2 或 Bcrypt 哈希存储。
- **F-AUTH-02 用户登录:** 校验账号密码,返回 `Access Token` (短效 15min) 和 `Refresh Token` (长效 7 天)。
- **F-AUTH-03 令牌刷新:** 使用有效的 Refresh Token 换取新的 Access Token。**旧的 Refresh Token 若被复用需触发安全警报(可选)或直接失效**。
- **F-AUTH-04 统一登出:** 强制使 Refresh Token 失效(需在 Redis 中建立黑名单或白名单机制)。
- **F-AUTH-05 密码重置:** 登录状态下修改密码,修改成功后强制吊销所有 Token。
### 2.2 用户与权限模块 (User & RBAC)
**预设角色:** 系统初始化必须包含以下三种角色。
|**角色代码**|**名称**|**权限描述**|
|---|---|---|
|`admin`|超级管理员|拥有系统所有权限 (用户管理、角色分配、内容强制删除)。|
|`editor`|内容编辑|拥有文章发布、审核、标签管理权限。不可管理用户。|
|`subscriber`|普通用户|仅拥有修改自身资料、发布评论、查看公开文章权限。|
- **F-USER-01 个人资料:** 查询与更新当前登录用户的昵称、头像 URL、简介。
- **F-USER-02 用户管理 (Admin):** 管理员可查看用户列表,封禁/解封用户状态。
- **F-RBAC-01 角色分配 (Admin):** 管理员可修改用户的角色(如将 User 提权为 Editor
### 2.3 内容核心模块 (CMS Core)
**核心逻辑:** 文章必须包含状态流转。
- **F-ART-01 文章 CRUD:**
- **创建:** 默认为 `Draft` (草稿) 状态。
- **字段:** 标题、内容、封面图 URL、作者 ID。
- **数据类型约束:** 文章内容字段在数据库层面建议使用 `TEXT``LONGTEXT` 类型,以完整承载 Markdown/HTML 长文本。
- **F-ART-02 文章状态流转:**
- 支持状态: `Draft` (草稿) -> `Pending` (待审核) -> `Published` (已发布) -> `Archived` (归档/软删除)。
- **F-ART-03 分类与标签:**
- 文章必须归属一个分类 (Category)。
- 文章可关联多个标签 (Tags)。
- **F-ART-04 内容审核 (Editor/Admin):**
- 拥有审核权限的角色可将 `Pending` 状态的文章改为 `Published` 或驳回至 `Draft`
- **F-ART-05 公开检索:**
-`Published` 状态的文章对外接口可见。支持按 分类、标签、标题关键词 搜索。
### 2.4 互动模块 (Interaction)
- **F-CMT-01 评论发布:** 登录用户可对 `Published` 文章发表评论。
- **F-CMT-02 评论管理:** 作者可删除自己文章下的评论Admin/Editor 可删除任何违规评论。
---
## 3. 非功能性需求 (Non-Functional Requirements)
**开发人员必须严格遵守以下技术约束:**
### 3.1 数据一致性
- **删除策略 [优化]:** 核心业务数据(用户、文章)原则上必须使用 Soft Delete (`deleted_at` 字段)。
- _例外条款:_ 涉及法律合规(如 GDPR 用户遗忘权)或垃圾数据清理时,经系统管理员明确审批操作后,允许提供物理删除接口。
- **事务:** 文章发布与标签关联必须在同一个 Database Transaction 中完成。
### 3.2 性能与缓存
- **API 响应:** 95% 的请求响应时间需 < 200ms (不含网络延迟)。
- **缓存策略:**
- 建议对 **高频读取且低频修改** 的数据(如用户信息 `/profile`、热门文章详情 `/article/:id`)实施缓存策略。
- 具体的缓存实现Redis Key 设计、TTL 时长、Cache-Aside 或 Write-Through 模式)由开发团队根据实际压测结果灵活调整,不强制硬编码 TTL。
### 3.3 安全性
- **SQL 注入:** 严禁拼接 SQL必须使用 GORM 参数化查询。
- **敏感数据:** 密码、RefreshToken 严禁明文出现在日志中。
- **接口保护:** 除登录、注册、公开文章列表外,所有接口必须通过 JWT 中间件校验。
### 3.4 工程规范
- **Schema:** 数据库表结构变更必须提供 Up/Down SQL 迁移脚本。
- **Doc:** 所有 API 必须自动生成 Swagger 文档。
---
## 4. 不在范围 (Out of Scope)
**以下功能明确不包含在本次 Phase 1 开发中:**
1. **❌ 第三方登录:** 不做微信/GitHub/Google 登录。
2. **❌ 消息推送/通知:** 不做系统内通知。
3. **❌ 文件存储服务 (OSS):** 仅处理 URL 字符串,不处理文件流上传。
4. **❌ 复杂的富文本处理:** 后端仅存储字符串,不解析 HTML。
5. **❌ 支付与订单:** 不包含任何电商逻辑。
---
## 5. 核心数据实体关系图 (ER 简述)
- **User** (1) <-> (N) **Article**
- **User** (1) <-> (N) **Comment**
- **Article** (1) <-> (N) **Comment**
- **Article** (N) <-> (1) **Category**
- **Article** (N) <-> (N) **Tag** (Many-to-Many)
```