G16第 1 / 1 课时未开始内容版本 1.0.0 · 核验于 2026-10-26

Go 服务复盘

Go 服务复盘 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。

学习目标

这课不写新功能,做一次有证据的可靠性复盘:用检查命令审出并发、context、数据库、错误处理、测试五个维度的真实问题,选一个最痛的,用前后对比的方式修掉它。

问题场景

p7-go-bookmark 能跑了,但「能跑」和「靠得住」之间隔着一次认真的复盘。复盘最忌凭感觉重写:要有输出作证据——race 报告、超时日志、慢查询耗时。方法论只有一句:先用工具审出问题清单,再挑影响最大的一个,修完留前后对比。

核心解释

五个维度各有对应的取证命令:

go vet ./...                    # 静态可疑点:锁拷贝、Printf 参数
go test ./... -race -count=5    # 竞争检测重复跑,提高检出率
gofmt -l .                      # 格式漂移
go test -cover ./...            # 覆盖薄弱点,重点看错误分支
curl -s -o /dev/null -w "%{http_code} %{time_total}\n" http://127.0.0.1:8080/healthz
                                # 健康检查的真实状态码与耗时

审计清单按维度过一遍:

  • 并发:还有没有裸 go 语句?每个后台任务是否都能被 cancel 且被 wg.Wait 等到?
  • context:store 的每个方法是否收 ctx 并使用 *Context 调用?grep 一遍不带 Context 后缀的数据库调用。
  • 数据库:连接池参数有没有设?事务边界是否覆盖多表写入?rows 是否全部 Close?
  • 错误:包装是否全用 %w?handler 是否把 ErrNotFound/ErrDuplicate 翻译成 404/409 而不是 500?
  • 测试:错误路径有没有用例?-race 是否进了 CI 或提交前习惯?

举个「审出并修掉」的完整案例。审计发现压测时偶发 SQLITE_BUSY(database is locked),证据是日志里每小时几条的 busy 错误。根因是 SQLite 单写者,而连接池默认无上限,多个写事务互相踩。修复两行:

// 修复前:默认连接池,写并发互踩
db, err := sql.Open("sqlite", "bookmark.db")

// 修复后:驱动层等锁 + 写连接收敛
db, err := sql.Open("sqlite", "file:bookmark.db?_pragma=busy_timeout(5000)")
db.SetMaxOpenConns(1)

busy_timeout 让驱动在锁被占时等最多 5 秒而不是立刻报错,SetMaxOpenConns(1) 把并发写彻底串行化(G08 里已经埋了这行,这里说明它为什么在)。修完复跑压测,busy 错误归零——证据链闭合。复盘的方向不是发现十个问题全修,而是把「发生频率 × 影响面」最高的一个修到有复验证据,其余记进 TODO 带着优先级走。

示例拆解

把复盘固化成一页文档(README 附录或 REVIEW.md),结构固定:

## 复盘 2026-10-26
发现:
1. [高] 偶发 SQLITE_BUSY —— 压测日志每小时 3-5 条
2. [中] store 有 2 处 Query 未换 *Context 版本 —— grep 输出为证
3. [低] coverage 63%,错误分支未覆盖 —— cover 输出为证
已修:问题 1(busy_timeout + 单连接,复验:压测 10 分钟零 busy)
遗留:2、3 进 TODO,下次迭代处理

「发现带证据、修复带复验、遗留带优先级」三件套让复盘可追溯——下次复盘先看上次遗留清没清。排序体现判断力:低频但高影响的(退出时可能丢数据)要排在高频但无害的(日志格式不统一)前面。这一课之后,G16 的复盘文档和 p7-go-bookmark 一起构成整条 Go 线的结课作品。

动手任务

  1. 对自己的 p7-go-bookmark 跑完五条取证命令,按固定格式写发现清单,每条附命令输出摘录。
  2. 选一条高优先级问题修复,记录修复前的复现方式与修复后的复验输出。
  3. 把遗留问题写成 README 的 TODO 小节,标注优先级与建议方案。

常见错误

  • 凭印象重写而不取证:改了一堆没有一条输出证明修了真问题,还可能引入新 bug。
  • 一次复盘修十个问题:每个都修一半,没有复验证据,问题实际状态不可知。
  • 复盘结论只存在脑子里:不落文档,下次迭代原问题复发,排查从零开始。
  • 只看覆盖率数字:63% 但关键错误分支全覆盖,比 81% 但错误分支全空更安全,覆盖要按分支看。

检查与复盘

完成下方检查题。自查清单:

  • 五个维度的取证命令都跑过且留有输出
  • 至少一个问题完成「现象-根因-修复-复验」完整证据链
  • 遗留问题有文档、有优先级,下次复盘可追溯

参考资料

检查题共 1 题,提交后立即显示解析
答案由服务端判定;答错的题会自动进入复习计划。
Q1多选中等(多选,全部选对才算正确)

复盘一个 Go 后端服务(Go 1.22+)的上线检查单,下列条目正确的有哪些?(多选)

读完这一课了?

标记完成后,工作台会安排接下来的学习。

Command Palette

Search for a command to run...