27 KiB
27 KiB
核心模块
**本文引用的文件** - [cmd/server/main.go](file://cmd/server/main.go) - [internal/router/router.go](file://internal/router/router.go) - [internal/config/config.go](file://internal/config/config.go) - [internal/database/mysql.go](file://internal/database/mysql.go) - [internal/cache/redis.go](file://internal/cache/redis.go) - [internal/handler/brand.go](file://internal/handler/brand.go) - [internal/handler/model.go](file://internal/handler/model.go) - [internal/handler/model_list.go](file://internal/handler/model_list.go) - [internal/handler/device.go](file://internal/handler/device.go) - [internal/handler/health.go](file://internal/handler/health.go) - [internal/repository/brand.go](file://internal/repository/brand.go) - [internal/repository/model.go](file://internal/repository/model.go) - [internal/model/brand.go](file://internal/model/brand.go) - [internal/model/model.go](file://internal/model/model.go) - [internal/response/response.go](file://internal/response/response.go) - [internal/search/meilisearch.go](file://internal/search/meilisearch.go) - [pkg/encode/base64.go](file://pkg/encode/base64.go) - [pkg/logger/logger.go](file://pkg/logger/logger.go)目录
简介
本文件围绕 Luxsin 应用 API 的核心模块进行系统化文档化,重点覆盖以下方面:
- 业务处理器(Handler):负责接收请求、解析参数、调用仓库层、封装统一响应。
- 数据访问层(Repository):负责与数据库交互,执行查询与扫描逻辑。
- 数据模型(Model):定义持久化与对外传输的数据结构。
- 统一响应(Response):规范 HTTP 响应体格式,提供便捷的构造方法。
- 依赖注入与启动流程:从配置加载到服务启动、中间件装配、路由注册与资源管理。
- 错误处理与日志记录:在各层中的一致性错误处理与可观测性。
- 扩展最佳实践:如何新增模块、如何复用编码器、如何接入缓存与搜索引擎。
- 性能优化与并发安全:连接池、超时控制、上下文传播、Redis 并发安全。
项目结构
项目采用分层与按功能域组织的结构:
- cmd/server:应用入口,负责配置加载、外部依赖初始化、HTTP 服务器启动与优雅关闭。
- internal/config:集中式配置加载与校验。
- internal/database:数据库连接与连接池配置。
- internal/cache:Redis 客户端初始化。
- internal/search:搜索引擎客户端封装。
- internal/router:路由注册与中间件装配。
- internal/handler:业务处理器,面向具体 API 路由。
- internal/repository:数据访问层,封装 SQL 查询。
- internal/model:领域模型与传输模型。
- internal/response:统一响应体封装。
- pkg/*:通用工具包(如编码器、日志)。
graph TB
subgraph "入口与配置"
MAIN["cmd/server/main.go<br/>应用入口"]
CFG["internal/config/config.go<br/>配置加载"]
end
subgraph "基础设施"
DB["internal/database/mysql.go<br/>MySQL 连接与池"]
RDS["internal/cache/redis.go<br/>Redis 客户端"]
SRCH["internal/search/meilisearch.go<br/>搜索引擎客户端"]
LOG["pkg/logger/logger.go<br/>日志"]
end
subgraph "服务编排"
RT["internal/router/router.go<br/>路由与中间件"]
end
subgraph "业务层"
H_BRAND["internal/handler/brand.go<br/>品牌处理器"]
H_MODEL["internal/handler/model.go<br/>型号处理器"]
H_MLIST["internal/handler/model_list.go<br/>型号搜索处理器"]
H_DEV["internal/handler/device.go<br/>设备上报处理器"]
H_HEALTH["internal/handler/health.go<br/>健康检查处理器"]
end
subgraph "数据访问与模型"
REPO_BRAND["internal/repository/brand.go<br/>品牌仓库"]
REPO_MODEL["internal/repository/model.go<br/>型号仓库"]
MODEL_BRAND["internal/model/brand.go<br/>品牌模型"]
MODEL_MODEL["internal/model/model.go<br/>型号模型"]
RESP["internal/response/response.go<br/>统一响应"]
ENC["pkg/encode/base64.go<br/>Base64 编码器"]
end
MAIN --> CFG
MAIN --> DB
MAIN --> RDS
MAIN --> SRCH
MAIN --> LOG
MAIN --> RT
RT --> H_HEALTH
RT --> H_BRAND
RT --> H_MODEL
RT --> H_MLIST
RT --> H_DEV
H_BRAND --> REPO_BRAND
H_MODEL --> REPO_MODEL
H_MLIST --> SRCH
H_DEV --> RDS
REPO_BRAND --> DB
REPO_MODEL --> DB
H_BRAND --> RESP
H_MODEL --> RESP
H_MLIST --> RESP
H_HEALTH --> RESP
H_BRAND --> ENC
H_MODEL --> ENC
H_MLIST --> ENC
图表来源
- cmd/server/main.go:22-95
- internal/router/router.go:14-41
- internal/config/config.go:18-64
- internal/database/mysql.go:14-46
- internal/cache/redis.go:10-16
- internal/handler/brand.go:19-49
- internal/handler/model.go:19-50
- internal/handler/model_list.go:19-56
- internal/handler/device.go:19-84
- internal/handler/health.go:10-18
- internal/repository/brand.go:16-50
- internal/repository/model.go:16-94
- internal/model/brand.go:3-6
- internal/model/model.go:5-14
- internal/response/response.go:9-36
- pkg/encode/base64.go
章节来源
核心组件
本节聚焦 Handler、Repository、Model、Response 四大核心模块的职责、协作方式与实现要点。
-
Handler(业务处理器)
- 职责:解析请求参数、调用仓库或外部服务、封装统一响应;必要时进行参数校验与基础编码处理。
- 典型实现位置:
-
Repository(数据访问层)
- 职责:封装 SQL 查询、参数拼装、结果扫描与错误包装;支持上下文传播与超时控制。
- 典型实现位置:
-
Model(数据模型)
- 职责:定义数据库字段映射与 JSON 序列化字段名;可选字段使用指针以区分空值与缺省。
- 典型实现位置:
-
Response(统一响应)
- 职责:统一响应体结构与常用状态构造方法,保证前后端契约一致。
- 典型实现位置:
章节来源
- internal/handler/brand.go:19-49
- internal/handler/model.go:19-50
- internal/handler/model_list.go:19-56
- internal/handler/device.go:19-84
- internal/handler/health.go:10-18
- internal/repository/brand.go:16-50
- internal/repository/model.go:16-94
- internal/model/brand.go:3-6
- internal/model/model.go:5-14
- internal/response/response.go:9-36
架构总览
下图展示从请求进入至响应返回的关键路径,以及各层之间的依赖关系与调用方向。
sequenceDiagram
participant C as "客户端"
participant G as "Gin 路由<br/>internal/router/router.go"
participant H as "业务处理器<br/>internal/handler/*"
participant R as "仓库层<br/>internal/repository/*"
participant DB as "数据库<br/>internal/database/mysql.go"
participant S as "搜索引擎<br/>internal/search/meilisearch.go"
participant RC as "Redis<br/>internal/cache/redis.go"
participant RESP as "统一响应<br/>internal/response/response.go"
C->>G : "HTTP 请求"
G->>H : "匹配路由并调用处理器"
alt "品牌/型号列表"
H->>R : "调用仓库查询"
R->>DB : "执行 SQL 查询"
DB-->>R : "返回结果集"
R-->>H : "返回模型切片"
else "型号搜索"
H->>S : "调用搜索引擎"
S-->>H : "返回搜索结果"
else "设备上报"
H->>RC : "写入 Redis Hash"
RC-->>H : "返回写入结果"
end
H->>RESP : "构造统一响应"
RESP-->>C : "HTTP 响应"
图表来源
- internal/router/router.go:21-38
- internal/handler/brand.go:30-35
- internal/handler/model.go:31-36
- internal/handler/model_list.go:37-42
- internal/handler/device.go:70-78
- internal/repository/brand.go:31-35
- internal/repository/model.go:42-46
- internal/response/response.go:15-21
详细组件分析
Handler 层
- 品牌处理器(BrandHandler)
- 关键点:读取查询参数、调用仓库、错误日志与统一错误响应、可选 Base64 响应。
- 参考路径:internal/handler/brand.go:26-49
- 型号处理器(ModelHandler)
- 关键点:多条件查询(品牌/名称模糊)、上下文传播、统一响应与错误处理。
- 参考路径:internal/handler/model.go:26-50
- 型号搜索处理器(ModelListHandler)
- 关键点:搜索引擎客户端调用、count 参数限制、统一响应。
- 参考路径:internal/handler/model_list.go:26-56
- 设备上报处理器(DeviceHandler)
- 关键点:参数校验、日志记录、Redis Hash 写入、错误处理。
- 参考路径:internal/handler/device.go:26-84
- 健康检查处理器(HealthHandler)
- 关键点:简单响应,使用统一响应体。
- 参考路径:internal/handler/health.go:14-18
classDiagram
class BrandHandler {
-repo : BrandRepository
-log : Logger
+GetBrand(c)
}
class ModelHandler {
-repo : ModelRepository
-log : Logger
+GetModel(c)
}
class ModelListHandler {
-search : SearchClient
-log : Logger
+ModelList(c)
}
class DeviceHandler {
-redis : RedisClient
-log : Logger
+ReportDevInfo(c)
}
class HealthHandler {
+Check(c)
}
BrandHandler --> BrandRepository : "依赖"
ModelHandler --> ModelRepository : "依赖"
ModelListHandler --> SearchClient : "依赖"
DeviceHandler --> RedisClient : "依赖"
图表来源
- internal/handler/brand.go:14-24
- internal/handler/model.go:14-24
- internal/handler/model_list.go:14-24
- internal/handler/device.go:14-24
- internal/handler/health.go:8-12
章节来源
- internal/handler/brand.go:19-49
- internal/handler/model.go:19-50
- internal/handler/model_list.go:19-56
- internal/handler/device.go:19-84
- internal/handler/health.go:10-18
Repository 层
- 品牌仓库(BrandRepository)
- 关键点:条件查询、排序、结果扫描。
- 参考路径:internal/repository/brand.go:20-50
- 型号仓库(ModelRepository)
- 关键点:多条件拼装、LIKE 模糊匹配、NullString 处理、上下文传播。
- 参考路径:internal/repository/model.go:20-94
classDiagram
class BrandRepository {
-db : sql.DB
+List(ctx, brandName) []Brand
}
class ModelRepository {
-db : sql.DB
+List(ctx, brandName, modelName) []Model
}
class Brand {
+id : int
+name : string
}
class Model {
+id : int
+brandName : string
+name : string
+form : *string
+rig : *string
+source : *string
+eqKey : *string
+createAt : time
}
BrandRepository --> Brand : "返回"
ModelRepository --> Model : "返回"
图表来源
- internal/repository/brand.go:12-50
- internal/repository/model.go:12-94
- internal/model/brand.go:3-6
- internal/model/model.go:5-14
章节来源
- internal/repository/brand.go:16-50
- internal/repository/model.go:16-94
- internal/model/brand.go:3-6
- internal/model/model.go:5-14
Model 层
- 品牌模型(Brand)
- 字段:id、name
- 参考路径:internal/model/brand.go:3-6
- 型号模型(Model)
- 字段:id、brandName、name、form、rig、source、eqKey、createAt(可选字段使用指针)
- 参考路径:internal/model/model.go:5-14
章节来源
Response 层
- 统一响应体(Body)
- 字段:code、message、data
- 方法:OK、Fail、BadRequest、InternalError
- 参考路径:internal/response/response.go:9-36
flowchart TD
Start(["进入处理器"]) --> Build["构造响应体<br/>OK/Fail/BadRequest/InternalError"]
Build --> Send["通过 Gin 写入 HTTP 响应"]
Send --> End(["完成"])
图表来源
章节来源
编码与日志
- Base64 编码器(pkg/encode/base64.go)
- 用途:在处理器中对响应进行 Base64 编码后输出字符串。
- 使用场景:品牌与型号列表的可选 Base64 输出。
- 参考路径:internal/handler/brand.go:37-44,internal/handler/model.go:38-47,internal/handler/model_list.go:44-53
- 日志(pkg/logger/logger.go)
章节来源
- internal/handler/brand.go:37-44
- internal/handler/model.go:38-47
- internal/handler/model_list.go:44-53
- cmd/server/main.go:32-36
- internal/handler/brand.go:32-34
- internal/handler/model.go:33-35
- internal/handler/model_list.go:39-41
- internal/handler/device.go:47-49
- internal/handler/device.go:71-77
依赖分析
-
启动与依赖注入
- 配置加载:internal/config/config.go:18-64
- 数据库连接与池:internal/database/mysql.go:14-46
- Redis 客户端:internal/cache/redis.go:10-16
- 路由与中间件:internal/router/router.go:14-41
- 入口程序:cmd/server/main.go:22-95
-
处理器与仓库的依赖
- 品牌处理器依赖品牌仓库:internal/handler/brand.go:19-23 → internal/repository/brand.go:16
- 型号处理器依赖型号仓库:internal/handler/model.go:19-23 → internal/repository/model.go:16
- 型号搜索处理器依赖搜索引擎客户端:internal/handler/model_list.go:19-23 → internal/search/meilisearch.go
- 设备上报处理器依赖 Redis 客户端:internal/handler/device.go:19-23 → internal/cache/redis.go:10-16
graph LR
MAIN["cmd/server/main.go"] --> CFG["internal/config/config.go"]
MAIN --> DB["internal/database/mysql.go"]
MAIN --> RDS["internal/cache/redis.go"]
MAIN --> RT["internal/router/router.go"]
RT --> H_BRAND["internal/handler/brand.go"]
RT --> H_MODEL["internal/handler/model.go"]
RT --> H_MLIST["internal/handler/model_list.go"]
RT --> H_DEV["internal/handler/device.go"]
H_BRAND --> REPO_BRAND["internal/repository/brand.go"]
H_MODEL --> REPO_MODEL["internal/repository/model.go"]
H_MLIST --> SRCH["internal/search/meilisearch.go"]
H_DEV --> RDS
REPO_BRAND --> DB
REPO_MODEL --> DB
图表来源
- cmd/server/main.go:22-95
- internal/router/router.go:21-38
- internal/handler/brand.go:19-23
- internal/handler/model.go:19-23
- internal/handler/model_list.go:19-23
- internal/handler/device.go:19-23
- internal/repository/brand.go:16
- internal/repository/model.go:16
- internal/database/mysql.go:14-46
- internal/cache/redis.go:10-16
章节来源
- cmd/server/main.go:22-95
- internal/router/router.go:14-41
- internal/handler/brand.go:19-23
- internal/handler/model.go:19-23
- internal/handler/model_list.go:19-23
- internal/handler/device.go:19-23
- internal/repository/brand.go:16
- internal/repository/model.go:16
- internal/database/mysql.go:14-46
- internal/cache/redis.go:10-16
性能考量
- 数据库连接与池
- 最大并发连接数、最大空闲连接数、连接生命周期设置,有助于避免连接争用与资源泄漏。
- 参考路径:internal/database/mysql.go:33-35
- 上下文与超时
- 仓库层使用 QueryContext 与 PingContext,确保超时控制与取消传播。
- 参考路径:internal/repository/model.go:42-46,internal/database/mysql.go:37-43
- Redis 并发安全
- 单个 Redis 客户端实例在 Go 中是并发安全的,可在多个 goroutine 中共享。
- 参考路径:internal/handler/device.go:70-78
- 响应体积与 Base64
- 对于大列表响应,可启用 Base64 输出以减少传输体积,但会增加 CPU 开销。
- 参考路径:internal/handler/brand.go:37-44,internal/handler/model.go:38-47,internal/handler/model_list.go:44-53
- 搜索性能
- 搜索结果数量限制(count)可有效控制响应规模,避免过量数据传输。
- 参考路径:internal/handler/model_list.go:30-35
章节来源
- internal/database/mysql.go:33-35
- internal/repository/model.go:42-46
- internal/database/mysql.go:37-43
- internal/handler/device.go:70-78
- internal/handler/brand.go:37-44
- internal/handler/model.go:38-47
- internal/handler/model_list.go:30-35
- internal/handler/model_list.go:44-53
故障排查指南
- 常见错误类型与处理
- 数据库查询失败:在仓库层包装错误并在处理器记录日志与返回统一错误响应。
- 编码失败:在处理器捕获编码错误并返回统一错误响应。
- Redis 写入失败:记录错误并返回统一错误响应。
- 搜索失败:记录错误并返回统一错误响应。
- 日志定位
- 使用结构化日志记录关键上下文(如远程 IP、时间戳),便于问题追踪。
- 参考路径:internal/handler/device.go:47-50
章节来源
- internal/repository/model.go:43-44
- internal/handler/model.go:33-35
- internal/handler/brand.go:40-43
- internal/handler/model.go:40-43
- internal/handler/device.go:71-77
- internal/handler/model_list.go:39-41
- internal/handler/device.go:47-50
结论
本项目通过清晰的分层与职责分离,实现了可维护、可扩展且具备良好性能特征的 API 服务:
- Handler 专注于业务编排与响应封装;
- Repository 将数据访问细节抽象化;
- Model 明确数据契约;
- Response 提供统一的对外接口;
- 配合中间件、日志与统一错误处理,形成完整的可观测与可诊断体系;
- 在数据库连接池、上下文超时、Redis 并发安全与可选 Base64 响应等方面体现了工程化细节。
附录
- 扩展新模块的最佳实践
- 新增处理器:在 internal/handler 下创建处理器文件,定义结构体与依赖注入函数,实现业务方法并调用仓库或外部服务。
- 新增仓库:在 internal/repository 下创建仓库文件,实现查询方法、参数拼装与结果扫描,使用上下文与错误包装。
- 新增模型:在 internal/model 下定义结构体,注意可选字段使用指针;在仓库扫描函数中正确映射 NullString。
- 统一响应:优先使用 internal/response 提供的方法,保持前后端一致性。
- 参数与编码:利用 pkg/encode/base64.go 实现可选的 Base64 响应;在处理器中进行必要的参数校验与日志记录。
- 资源管理:在入口程序中集中初始化外部依赖(数据库、Redis、搜索引擎),并在退出时优雅关闭。