专题归档 · 2026 年 7 月(编辑分组,非实际写作日期)
从 Go 请求链路到 Python AI Runtime:我的全栈学习路线为何发生变化
从自己项目里的 User 调用链出发,转向读开源源码,再到分清 AI Application 与业务后端的职责。
最早决定系统学习 Go 和 Python 时,我没有完全从语言教程开始。我已经有靠 AI 辅助搭起来的项目,但一个问题越来越明显:项目能运行,不代表我真正理解了它为什么这样分层。
第一步:沿着真实请求反向阅读
我先跟着自己项目里 User 相关的一条请求读代码:
HTTP → Handler → Service → Repository → GORM Model → PostgreSQL
最直观的收获不是学会了多少 Go 语法,而是逐渐看清:Handler 负责 HTTP 边界,Service 负责业务组织,Repository 封装持久化;context.Context 应该沿请求链传递取消和截止时间,而不是无意义地全局存一份状态。
另一个很小但真实的学习节点,是 LastLoginAt *time.Time。它让我意识到,可空时间与 Go 的零值时间不是一个语义;在其他语言里习以为常的“没有值”,在 Go 结构体中需要明确的建模方式。更多例子已经拆到 Go 项目代码学习,这里不重复做一篇 GORM 教程。
第二步:不只读自己 Vibe Coding 出来的项目
随着阅读深入,我反而开始怀疑一件事:如果项目原本就由 AI 快速生成,把它当成唯一架构范本会不会有问题?
我因此去看 ArdanLabs Service、Memos 等公开项目的代码组织。这时第一次认真比较两种切法:
- 按技术职责放顶层:API、业务、基建层先分开,再在内部组织领域;
- 按业务领域放顶层:Goal、Task、Reminder 等包先分开,每个包再容纳自己的 Domain、Application 和 Infrastructure。
它们不是简单的优劣关系。前者容易沿请求的垂直链追踪;后者在业务边界清楚时更利于保持领域的独立演进。
读 Memos 时,又让我注意到 API 契约与 Transport 封装的区别:统一前后端 DTO 不意味着已经把 gRPC/HTTP 的传输细节从业务调用方完全隔离。这类比较也已经写进 Go 开源源码阅读。
第三步:进入 Python AI Application,问题从语法变成边界
准备学习 AI Application 时,我一度在 Pydantic AI、LangGraph、LangChain 等框架之间来回比较,也发现 BodySense 当时使用的框架并不是我原计划拿来学基础 Python 的那一个。
后来把框架名字拿掉,我更愿意按职责理解系统:
Model / Provider 管理模型能力与接入;Context Builder 决定这一轮需要给模型什么数据;Tools 将可执行操作接到受控代码;Workflow 定义可预测的任务路径;Agent 则可能持续根据结果做决策。这些运行在一组横向能力之上:权限、状态、超时、取消、重试、事件和检查点。
这个过程中,我越来越认同一个分工:
AI 层负责不确定性的工作;业务后端负责确定性的工作。
现在看来,这句话比“我要先学哪个 Agent 框架”更有用。模型可以给出诊断或下一步操作的候选,但业务规则、权限和状态变更不应该因为模型输出看起来合理就被跳过。
第四步:在 BodySense 的重构与测试里继续学
后来我在 BodySense 的 Diagnosis 支线接触到 Go Handler 测试、Python 的 Protocol、monkeypatch、Fake Service、httptest.Server 等技术。它们让我逐渐理解测试边界:
- Handler 测试是在验证请求/响应和服务调用的合同;
- Fake/Stub 是为了控制依赖,并不是拿一个真实大模型反复碰运气;
- 跨 Go/Python 的行为需要分别验证契约和错误路径。
具体学习过程已经记录在 Go Diagnosis Handler 测试 和 Python Diagnosis 学习。
回头看这条学习路线
对我而言,“全栈”逐渐不再等于 Go、Python、Vue/React 都会一点,而是能沿着业务请求和状态变化解释不同层的责任。从读 UserRepository 到追踪 AI 调用、Workflow Runtime 和测试依赖,实际上是在反复练同一件事:找出系统的边界与证据。
学到后来,我觉得最需要练习的不是背下每个框架的 API,而是能解释一条请求为什么经过这些层,状态由谁负责,以及出现错误时应该先从哪里查起。