第 7 章 · 框架设计思想与造轮子
“所谓的’框架’,不过是几个设计模式的组合——但组合的方式决定了一切。“
本章覆盖的课程
| 编号 | 课程 | 本章的产出 |
|---|---|---|
| 059 | 小马哥讲 Spring 核心编程思想 | Go 版 IoC/DI 容器 + AOP |
| 203 | 手把手带你写一个 MiniSpring | 完整的迷你框架 |
| 227 | 手把手带你写一个 MiniTomcat | Go 版 Web 容器 |
为什么要学 Java 框架思想
Go 生态的对应物
| Spring 概念 | Go 生态的对应物 |
|---|---|
| IoC 容器 | google/wire(编译期)、uber-go/dig(运行期) |
| 依赖注入 | 构造函数注入(Go 的惯例) |
| AOP | 中间件(middleware)、装饰器 |
| Bean 生命周期 | 构造函数 + Close() |
| @Component 扫描 | 显式注册(Go 没有注解) |
| 事务管理 | 手动 or sqlx 的 Tx |
| Spring MVC | gin、echo、chi |
关键洞察:思想是一样的,实现方式不同。
Spring 的做法:
用注解 + 反射 + 运行时的 Bean 容器
→ 灵活,但"魔法"多,启动慢,错误在运行时才暴露
Go 的做法:
用代码生成(wire)或者显式注册(dig)
→ 简单,编译期检查,启动快,但没那么灵活
这正是第 1 章讲的”把信息提前到编译期几乎总是划算”在框架层面的体现。
章节结构
| 文档 | 内容 |
|---|---|
00-设计推演:从零造一个 Web 框架.md | ★ 必读开篇:I/O 模型(线程→轮询→select→epoll→goroutine)、路由(if-else→map→正则→radix tree)、中间件(重复→函数→洋葱模型→扁平化)三条推导链 |
01-IoC 与 AOP:依赖注入与横切关注点.md | 控制反转、依赖注入、反射实现 DI、拦截器链 |
02-手写 Web 容器:从 Socket 到 MVC.md | HTTP 协议解析、路由树、中间件、Go 版 MiniTomcat |
★ 先读
00-设计推演。 它把 Web 框架拆成三条独立的失败链条各推一遍: 为什么每连接一线程撑不过 C10K、为什么 map 做不了路径参数、为什么”提取成函数” 解决不了样板代码(答案是要靠控制反转)。走完你会发现:Web 框架没有魔法,三个组件全是被具体问题逼出来的。
学完这一章,你应该能
- 解释 IoC 和 DI 的区别,以及它们解决什么问题
- 用 Go 手写一个 DI 容器(支持构造函数注入、依赖图解析、循环依赖检测)
- 解释
wire(编译期)和dig(运行期)的设计差异 - 用 Go 实现 AOP 拦截器链(对比 Go 的 middleware 模式)
- 用 Go 手写一个 HTTP 服务器(不用
net/http) - 理解路由树(radix tree)的实现
- 设计一个插件化的框架架构
贯穿全章的核心思想
思想 1:框架的本质是”控制反转”
不用框架:
你的代码 ──调用──► 库函数
(你控制流程)
用框架:
框架 ──调用──► 你的代码
(框架控制流程,你只填"回调")
这就是 IoC(Inversion of Control)——“好莱坞原则”:Don’t call us, we’ll call you.
思想 2:复杂度要么在框架,要么在用户代码
Spring 的选择:
复杂度在框架(反射、代理、容器)
→ 用户代码简单(加个注解就行)
→ 代价:启动慢、调试难、"魔法"多
Go 的选择:
复杂度在用户代码(显式调用、显式注册)
→ 框架简单(就是几个函数)
→ 代价:样板代码多
没有对错,只有取舍。 理解了这一点,你就能判断”什么时候该引入框架,什么时候该自己写”。
开始阅读:00-设计推演:从零造一个 Web 框架