创建仓库
This commit is contained in:
80
Go项目实战/中间件/推荐的中间件目录演进策略.md
Normal file
80
Go项目实战/中间件/推荐的中间件目录演进策略.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
tags: []
|
||||
aliases:
|
||||
- 🏗️ 推荐的中间件目录演进策略
|
||||
date created: 星期三, 十二月 10日 2025, 11:08:17 上午
|
||||
date modified: 星期三, 十二月 10日 2025, 11:08:58 上午
|
||||
---
|
||||
这是一个非常有前瞻性的问题。你现在的顾虑完全符合 **“高内聚、低耦合”** 的架构直觉。
|
||||
|
||||
在企业级 Go 项目中,如果把所有中间件(Auth, CORS, RateLimit, Logger, Recovery, Trace…)都堆在 `internal/middleware/` 根目录下,确实会变成一个“大杂烩”,导致文件结构不明晰。
|
||||
|
||||
基于 **Modular Clean Architecture** 和 **Go 最佳实践**,我推荐采用 **“按复杂度分层 (Complexity-Based Layering)”** 的混合策略。
|
||||
|
||||
# 🏗️ 推荐的中间件目录演进策略
|
||||
|
||||
我们不需要一开始就过度设计(Over-engineering),而是制定一条**规则**:
|
||||
|
||||
1. **通用基础设施 (Universal Infra):** 逻辑简单、无状态、单文件即可解决的,直接放在根目录。
|
||||
2. **复杂业务逻辑 (Complex Logic):** 需要定义配置结构体、辅助函数、或依赖外部库较重的,**建立子目录**。
|
||||
|
||||
## 修正后的目录蓝图
|
||||
|
||||
```Plaintext
|
||||
internal/
|
||||
└── middleware/
|
||||
│
|
||||
│ # --- Level 1: 通用基础设施 (直接放根目录) ---
|
||||
├── recovery.go # [现有] 及其简单,就一个函数
|
||||
├── not_found.go # [现有] 就一个 Handler
|
||||
├── cors.go # [未来] CORS 配置通常单文件搞定
|
||||
├── trace.go # [未来] 注入 TraceID
|
||||
│
|
||||
│ # --- Level 2: 复杂中间件 (独立子包) ---
|
||||
├── auth/ # [未来] 认证模块很复杂
|
||||
│ ├── jwt.go # JWT 解析逻辑
|
||||
│ └── context.go # 将 UserID 注入 Context 的辅助函数
|
||||
│
|
||||
├── ratelimit/ # [未来] 限流可能涉及 Redis 脚本
|
||||
│ ├── ip_limiter.go
|
||||
│ └── lua_script.go
|
||||
│
|
||||
└── log/ # [未来] 访问日志
|
||||
└── access_logger.go
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 💡 为什么要这样设计?(Rationale)
|
||||
|
||||
## 1. Go 的包导入体验 (Import DX)
|
||||
|
||||
- 对于通用中间件:
|
||||
|
||||
我们在 main.go 里的调用通常希望长这样:
|
||||
|
||||
```Go
|
||||
// 读起来很通顺:使用中间件 -> 恢复、日志、CORS
|
||||
r.Use(middleware.Recovery())
|
||||
r.Use(middleware.Logger())
|
||||
r.Use(middleware.Cors())
|
||||
```
|
||||
|
||||
如果强行把 `recovery.go` 放到 `middleware/recovery/recovery.go`,调用就会变成 `recovery.New()`,这在语义上丢失了“这是一个中间件”的上下文,而且引入了太多的包名。
|
||||
|
||||
- 对于复杂中间件:
|
||||
|
||||
认证通常需要配置:
|
||||
|
||||
```Go
|
||||
// 读起来清楚:这是 Auth 相关的中间件
|
||||
r.Use(auth.Middleware(auth.Config{…}))
|
||||
```
|
||||
|
||||
这时候引入 `auth` 子包是合理的。
|
||||
|
||||
## 2. 避免循环依赖
|
||||
|
||||
`recovery.go` 和 `not_found.go` 属于**基础设施的底座**,它们几乎不依赖其他业务代码(除了我们刚才定义的 `app` 包)。将它们放在根目录,可以方便地被其他子包引用(虽然中间件之间很少互相引用)。
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user