366 lines
16 KiB
Markdown
366 lines
16 KiB
Markdown
# 统一响应
|
||
|
||
<cite>
|
||
**本文引用的文件**
|
||
- [internal/response/response.go](file://internal/response/response.go)
|
||
- [internal/handler/health.go](file://internal/handler/health.go)
|
||
- [internal/handler/brand.go](file://internal/handler/brand.go)
|
||
- [internal/handler/model.go](file://internal/handler/model.go)
|
||
- [internal/router/router.go](file://internal/router/router.go)
|
||
- [internal/middleware/logger.go](file://internal/middleware/logger.go)
|
||
- [internal/middleware/request_id.go](file://internal/middleware/request_id.go)
|
||
- [internal/middleware/cors.go](file://internal/middleware/cors.go)
|
||
- [pkg/encode/base64.go](file://pkg/encode/base64.go)
|
||
- [pkg/logger/logger.go](file://pkg/logger/logger.go)
|
||
- [cmd/server/main.go](file://cmd/server/main.go)
|
||
- [README.md](file://README.md)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖分析](#依赖分析)
|
||
7. [性能考虑](#性能考虑)
|
||
8. [故障排查指南](#故障排查指南)
|
||
9. [结论](#结论)
|
||
10. [附录](#附录)
|
||
|
||
## 简介
|
||
本文件系统化阐述 Luxsin 应用 API 的“统一响应”模块,围绕响应格式设计原则、实现机制与使用规范展开,覆盖响应结构、状态码策略、错误处理、国际化与调试信息、扩展与自定义选项、性能优化与最佳实践。目标是帮助初学者快速理解统一响应在 API 设计中的一致性价值,同时为高级开发者提供实现细节与扩展路径。
|
||
|
||
## 项目结构
|
||
统一响应模块位于 internal/response,配合各 handler 在业务层统一输出 JSON 结构;路由与中间件负责请求生命周期管理与日志记录;编码工具提供可选的 Base64 响应能力;日志与服务器入口负责运行时配置与生命周期控制。
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "应用入口"
|
||
MAIN["cmd/server/main.go"]
|
||
end
|
||
subgraph "HTTP 层"
|
||
ROUTER["internal/router/router.go"]
|
||
M_REQID["internal/middleware/request_id.go"]
|
||
M_LOG["internal/middleware/logger.go"]
|
||
M_CORS["internal/middleware/cors.go"]
|
||
end
|
||
subgraph "业务层"
|
||
HANDLER_HEALTH["internal/handler/health.go"]
|
||
HANDLER_BRAND["internal/handler/brand.go"]
|
||
HANDLER_MODEL["internal/handler/model.go"]
|
||
end
|
||
subgraph "通用能力"
|
||
RESP["internal/response/response.go"]
|
||
ENCODE["pkg/encode/base64.go"]
|
||
LOGPKG["pkg/logger/logger.go"]
|
||
end
|
||
MAIN --> ROUTER
|
||
ROUTER --> M_REQID
|
||
ROUTER --> M_LOG
|
||
ROUTER --> M_CORS
|
||
ROUTER --> HANDLER_HEALTH
|
||
ROUTER --> HANDLER_BRAND
|
||
ROUTER --> HANDLER_MODEL
|
||
HANDLER_HEALTH --> RESP
|
||
HANDLER_BRAND --> RESP
|
||
HANDLER_MODEL --> RESP
|
||
HANDLER_BRAND --> ENCODE
|
||
HANDLER_MODEL --> ENCODE
|
||
MAIN --> LOGPKG
|
||
```
|
||
|
||
图表来源
|
||
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
|
||
- [internal/router/router.go:14-42](file://internal/router/router.go#L14-L42)
|
||
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
|
||
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
|
||
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
|
||
- [internal/handler/health.go:14-19](file://internal/handler/health.go#L14-L19)
|
||
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
|
||
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
|
||
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
|
||
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
|
||
- [pkg/logger/logger.go:8-20](file://pkg/logger/logger.go#L8-L20)
|
||
|
||
章节来源
|
||
- [README.md:1-123](file://README.md#L1-L123)
|
||
- [cmd/server/main.go:22-96](file://cmd/server/main.go#L22-L96)
|
||
- [internal/router/router.go:14-42](file://internal/router/router.go#L14-L42)
|
||
|
||
## 核心组件
|
||
- 统一响应体结构
|
||
- 字段:code、message、data(可选)
|
||
- 语义:code 为业务/协议态码;message 为人类可读消息;data 承载具体业务数据
|
||
- 响应函数族
|
||
- OK:成功响应,code=0,message="ok"
|
||
- Fail:通用失败响应,传入 HTTP 状态码、业务态码与消息
|
||
- BadRequest:快捷失败,HTTP 400,业务态码 40000
|
||
- InternalError:快捷失败,HTTP 500,业务态码 50000
|
||
|
||
这些函数统一封装了 JSON 输出,确保所有 handler 以一致的结构返回,便于客户端解析与前端统一处理。
|
||
|
||
章节来源
|
||
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
|
||
|
||
## 架构总览
|
||
统一响应贯穿“路由 -> 中间件 -> 处理器 -> 统一响应”的调用链路。中间件负责请求标识、跨域与日志;处理器完成参数解析、业务执行与错误处理;统一响应模块负责最终的 JSON 输出。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant R as "路由/中间件"
|
||
participant H as "处理器"
|
||
participant S as "统一响应"
|
||
C->>R : "HTTP 请求"
|
||
R->>R : "请求ID/日志/CORS"
|
||
R->>H : "进入处理器"
|
||
H->>H : "参数解析/业务执行"
|
||
alt "成功"
|
||
H->>S : "OK(data)"
|
||
S-->>C : "{code,message,data}"
|
||
else "失败"
|
||
H->>S : "Fail/400/500(...)"
|
||
S-->>C : "{code,message}"
|
||
end
|
||
```
|
||
|
||
图表来源
|
||
- [internal/router/router.go:14-42](file://internal/router/router.go#L14-L42)
|
||
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
|
||
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
|
||
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
|
||
- [internal/handler/health.go:14-19](file://internal/handler/health.go#L14-L19)
|
||
- [internal/response/response.go:15-37](file://internal/response/response.go#L15-L37)
|
||
|
||
## 详细组件分析
|
||
|
||
### 统一响应模块(internal/response)
|
||
- 设计要点
|
||
- 结构体 Body 仅包含三字段,简洁明确,避免冗余
|
||
- OK/Fail/BadRequest/InternalError 一组函数覆盖常见场景
|
||
- 通过 gin.Context 输出 JSON,保持与框架一致的 Content-Type 与状态码
|
||
- 数据流
|
||
- 输入:gin.Context、业务数据或错误信息
|
||
- 输出:标准化 JSON 响应
|
||
- 错误处理策略
|
||
- 成功路径:OK(data)
|
||
- 失败路径:Fail(HTTP状态, 业务态码, 消息),或快捷 BadRequest/InternalError
|
||
- 可扩展性
|
||
- 可新增更多快捷函数(如 Unauthorized、NotFound 等)
|
||
- 可引入国际化消息映射,按语言返回 message
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class Body {
|
||
+int code
|
||
+string message
|
||
+any data
|
||
}
|
||
class ResponseAPI {
|
||
+OK(c, data)
|
||
+Fail(c, httpStatus, code, message)
|
||
+BadRequest(c, message)
|
||
+InternalError(c, message)
|
||
}
|
||
ResponseAPI --> Body : "构造并输出"
|
||
```
|
||
|
||
图表来源
|
||
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
|
||
|
||
章节来源
|
||
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
|
||
|
||
### 处理器与统一响应的协作
|
||
- 健康检查处理器
|
||
- 使用 OK 返回简单健康状态
|
||
- 品牌与型号处理器
|
||
- 从仓库层获取数据,发生错误时统一调用 InternalError
|
||
- 支持可选的 Base64 响应(通过参数 base64Resp 控制),内部先 JSON 编码再自定义 Base64 转换
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as "客户端"
|
||
participant H as "品牌/型号处理器"
|
||
participant Repo as "仓库层"
|
||
participant Resp as "统一响应"
|
||
C->>H : "GET /audio/getBrand?base64Resp=true"
|
||
H->>Repo : "List(...)"
|
||
Repo-->>H : "数据或错误"
|
||
alt "错误"
|
||
H->>Resp : "InternalError(...)"
|
||
Resp-->>C : "{code,message}"
|
||
else "成功"
|
||
H->>H : "按需JSON/Base64编码"
|
||
H-->>C : "JSON或Base64字符串"
|
||
end
|
||
```
|
||
|
||
图表来源
|
||
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
|
||
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
|
||
- [pkg/encode/base64.go:35-52](file://pkg/encode/base64.go#L35-L52)
|
||
- [internal/response/response.go:34-37](file://internal/response/response.go#L34-L37)
|
||
|
||
章节来源
|
||
- [internal/handler/health.go:14-19](file://internal/handler/health.go#L14-L19)
|
||
- [internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
|
||
- [internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
|
||
- [pkg/encode/base64.go:35-52](file://pkg/encode/base64.go#L35-L52)
|
||
|
||
### 中间件与日志
|
||
- 请求 ID 中间件
|
||
- 自动生成或透传 X-Request-ID,便于全链路追踪
|
||
- 日志中间件
|
||
- 记录状态码、方法、路径、耗时、IP、请求 ID、错误等
|
||
- 按状态码分级(info/warn/error)输出
|
||
- CORS 中间件
|
||
- 设置允许的源、方法、头,并暴露 X-Request-ID
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["进入中间件链"]) --> ReqID["生成/透传请求ID"]
|
||
ReqID --> Logger["记录请求开始"]
|
||
Logger --> Next["继续下一个处理器"]
|
||
Next --> Status{"状态码>=500?"}
|
||
Status --> |是| LogErr["记录错误日志"]
|
||
Status --> |否| Status400{"状态码>=400?"}
|
||
Status400 --> |是| LogWarn["记录告警日志"]
|
||
Status400 --> |否| LogInfo["记录正常日志"]
|
||
LogErr --> End(["结束"])
|
||
LogWarn --> End
|
||
LogInfo --> End
|
||
```
|
||
|
||
图表来源
|
||
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
|
||
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
|
||
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
|
||
|
||
章节来源
|
||
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
|
||
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
|
||
- [internal/middleware/cors.go:7-21](file://internal/middleware/cors.go#L7-L21)
|
||
|
||
### 编码与响应格式扩展
|
||
- Base64 响应
|
||
- 通过参数 base64Resp 控制是否返回自定义 Base64 编码的 JSON
|
||
- 内部先 JSON 编码,再使用自定义字符映射表进行 Base64 转换
|
||
- 与统一响应的结合
|
||
- 当启用 Base64 时,处理器直接输出字符串,不走统一响应的 JSON 结构
|
||
- 当未启用时,统一响应负责输出标准 JSON 结构
|
||
|
||
章节来源
|
||
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
|
||
- [internal/handler/brand.go:37-47](file://internal/handler/brand.go#L37-L47)
|
||
- [internal/handler/model.go:38-48](file://internal/handler/model.go#L38-L48)
|
||
|
||
## 依赖分析
|
||
- 统一响应依赖 Gin 上下文输出 JSON
|
||
- 处理器依赖统一响应与仓库/服务层
|
||
- 中间件依赖 Gin 与日志库
|
||
- 编码工具独立于响应模块,但被处理器条件使用
|
||
|
||
```mermaid
|
||
graph LR
|
||
Gin["github.com/gin-gonic/gin"] --> RESP["internal/response/response.go"]
|
||
RESP --> HANDLER_HEALTH["internal/handler/health.go"]
|
||
RESP --> HANDLER_BRAND["internal/handler/brand.go"]
|
||
RESP --> HANDLER_MODEL["internal/handler/model.go"]
|
||
HANDLER_BRAND --> ENCODE["pkg/encode/base64.go"]
|
||
HANDLER_MODEL --> ENCODE
|
||
ROUTER["internal/router/router.go"] --> M_REQID["internal/middleware/request_id.go"]
|
||
ROUTER --> M_LOG["internal/middleware/logger.go"]
|
||
ROUTER --> M_CORS["internal/middleware/cors.go"]
|
||
MAIN["cmd/server/main.go"] --> LOGPKG["pkg/logger/logger.go"]
|
||
```
|
||
|
||
图表来源
|
||
- [internal/response/response.go:3-7](file://internal/response/response.go#L3-L7)
|
||
- [internal/handler/health.go:4-6](file://internal/handler/health.go#L4-L6)
|
||
- [internal/handler/brand.go:7-11](file://internal/handler/brand.go#L7-L11)
|
||
- [internal/handler/model.go:7-12](file://internal/handler/model.go#L7-L12)
|
||
- [pkg/encode/base64.go:3-6](file://pkg/encode/base64.go#L3-L6)
|
||
- [internal/router/router.go:3-12](file://internal/router/router.go#L3-L12)
|
||
- [internal/middleware/request_id.go:7](file://internal/middleware/request_id.go#L7)
|
||
- [internal/middleware/logger.go:6-8](file://internal/middleware/logger.go#L6-L8)
|
||
- [internal/middleware/cors.go:4](file://internal/middleware/cors.go#L4)
|
||
- [cmd/server/main.go:12-19](file://cmd/server/main.go#L12-L19)
|
||
- [pkg/logger/logger.go:3-5](file://pkg/logger/logger.go#L3-L5)
|
||
|
||
章节来源
|
||
- [internal/response/response.go:3-7](file://internal/response/response.go#L3-L7)
|
||
- [internal/handler/brand.go:7-11](file://internal/handler/brand.go#L7-L11)
|
||
- [internal/handler/model.go:7-12](file://internal/handler/model.go#L7-L12)
|
||
- [pkg/encode/base64.go:3-6](file://pkg/encode/base64.go#L3-L6)
|
||
- [internal/router/router.go:3-12](file://internal/router/router.go#L3-L12)
|
||
- [internal/middleware/request_id.go:7](file://internal/middleware/request_id.go#L7)
|
||
- [internal/middleware/logger.go:6-8](file://internal/middleware/logger.go#L6-L8)
|
||
- [internal/middleware/cors.go:4](file://internal/middleware/cors.go#L4)
|
||
- [cmd/server/main.go:12-19](file://cmd/server/main.go#L12-L19)
|
||
- [pkg/logger/logger.go:3-5](file://pkg/logger/logger.go#L3-L5)
|
||
|
||
## 性能考虑
|
||
- 统一响应本身开销极低,主要成本在序列化与网络传输
|
||
- 对大对象响应,优先评估是否需要 Base64 压缩,注意额外的编码/解码成本
|
||
- 使用中间件的日志分级与请求 ID,有助于定位慢请求与异常点
|
||
- 生产环境建议开启 Gin Release 模式与合适的日志级别
|
||
|
||
## 故障排查指南
|
||
- 常见问题
|
||
- 业务错误未统一返回:检查处理器是否调用统一响应函数
|
||
- Base64 响应异常:确认参数 base64Resp 的取值与编码流程
|
||
- 日志缺失:确认中间件顺序与日志中间件是否正确设置
|
||
- 排查步骤
|
||
- 通过请求 ID 在日志中检索整条链路
|
||
- 关注状态码分级日志,定位 4xx/5xx 场景
|
||
- 若出现内部错误,统一响应会返回固定业务态码,便于前端/监控识别
|
||
|
||
章节来源
|
||
- [internal/middleware/logger.go:10-46](file://internal/middleware/logger.go#L10-L46)
|
||
- [internal/middleware/request_id.go:20-31](file://internal/middleware/request_id.go#L20-L31)
|
||
- [internal/response/response.go:34-37](file://internal/response/response.go#L34-L37)
|
||
|
||
## 结论
|
||
统一响应模块通过简洁一致的 JSON 结构与函数族,显著提升了 API 的可读性、可维护性与可观测性。配合中间件与日志体系,能够快速定位问题并保障用户体验。对于国际化与调试信息,建议在现有基础上扩展消息映射与上下文元数据,进一步增强一致性与可诊断性。
|
||
|
||
## 附录
|
||
|
||
### 响应结构与状态码定义
|
||
- 响应体字段
|
||
- code:业务/协议态码(成功通常为 0,失败为正整数)
|
||
- message:人类可读消息
|
||
- data:业务数据(可选)
|
||
- 常用状态码策略
|
||
- 成功:HTTP 200 + code=0
|
||
- 客户端错误:HTTP 400 + 业务态码 40000
|
||
- 服务器错误:HTTP 500 + 业务态码 50000
|
||
- 国际化与调试
|
||
- message 可按语言映射,data 可附加 traceId/requestId 等调试信息
|
||
- Base64 响应
|
||
- 通过参数 base64Resp 控制;启用后返回自定义 Base64 编码的 JSON 字符串
|
||
|
||
章节来源
|
||
- [internal/response/response.go:9-37](file://internal/response/response.go#L9-L37)
|
||
- [pkg/encode/base64.go:44-52](file://pkg/encode/base64.go#L44-L52)
|
||
|
||
### 使用示例(路径指引)
|
||
- 健康检查
|
||
- 路径:[internal/handler/health.go:14-19](file://internal/handler/health.go#L14-L19)
|
||
- 统一响应调用:[internal/response/response.go:15-21](file://internal/response/response.go#L15-L21)
|
||
- 获取品牌列表(含 Base64 选项)
|
||
- 路径:[internal/handler/brand.go:26-50](file://internal/handler/brand.go#L26-L50)
|
||
- 统一响应调用:[internal/response/response.go:23-28](file://internal/response/response.go#L23-L28)
|
||
- 编码逻辑:[pkg/encode/base64.go:35-52](file://pkg/encode/base64.go#L35-L52)
|
||
- 获取型号列表(含 Base64 选项)
|
||
- 路径:[internal/handler/model.go:26-51](file://internal/handler/model.go#L26-L51)
|
||
- 统一响应调用:[internal/response/response.go:23-28](file://internal/response/response.go#L23-L28)
|
||
- 编码逻辑:[pkg/encode/base64.go:35-52](file://pkg/encode/base64.go#L35-L52)
|
||
|
||
### 最佳实践
|
||
- 所有处理器统一使用统一响应函数输出
|
||
- 错误路径必须记录日志并返回统一响应
|
||
- 对大对象优先评估是否需要 Base64 响应
|
||
- 生产环境启用 Release 模式与合适的日志级别
|
||
- 通过中间件保证请求 ID 与跨域配置一致生效 |