事故复盘模板是结构化记录机制,需用Go定义含时间线、根因分类等字段的IncidentReport结构体,导出时规范处理时间格式与空值,并通过外部脚本渲染Markdown,确保每次填写推动真实改进。

事故复盘模板不是代码,而是结构化记录机制
Go 语言本身不提供「事故复盘模板」这种功能——它不是标准库里的一个函数或接口。所谓模板,本质是一套约定好的字段结构 + 填写规范 + 后续可检索的存储方式。你真正要做的,是用 Go 定义清晰的数据结构、约束必填项、支持导出为 JSON/Markdown,并能集成到内部 incident 工具流中。
定义 IncidentReport 结构体时必须包含时间线与根因字段
很多团队只记录现象和修复动作,漏掉「时间线(timeline)」和「根因分类(root_cause_category)」,导致后续无法聚合分析。建议结构体至少包含:
-
IncidentID:全局唯一,建议用ulid.MustNew()生成,比 UUID 更有序且可排序 -
StartedAt、ResolvedAt:用time.Time,别存字符串;缺失ResolvedAt表示仍在处理 -
Timeline:[]struct{ Time time.Time; Event string },避免用自由文本描述时间点 -
RootCauseCategory:预设枚举如"config_error"、"race_condition"、"dependency_timeout",别留空或写“未知” -
LessonsLearned:强制非空,且长度 > 20 字符(防敷衍)
用 json.Marshal 导出时要注意时间格式与空值处理
默认 json.Marshal 会把 time.Time 序列为 RFC3339 字符串(如 "2024-05-22T14:30:00+08:00"),这没问题;但若字段是 pointer 或嵌套 struct,容易导出 null 而非省略。实际填写中,应:
- 对非必填字段(如
PostmortemLink)用指针类型*string,并在 Marshal 前检查是否为 nil - 用
json:",omitempty"标签,但仅限于「真可选」字段;RootCauseCategory这类关键字段绝不能 omitempty - 导出前调用
Validate()方法(自定义),检查Timeline长度 ≥ 2(至少含开始+结束事件),否则拒绝序列化
不要在 Go 里硬编码 Markdown 模板渲染逻辑
有人试图用 text/template 在 Go 中拼接 Markdown 复盘文档,结果越写越重、难维护。正确做法是:
立即学习“go语言免费学习笔记(深入)”;
- Go 只负责生成结构化数据(JSON/YAML),例如输出到
/tmp/incident-20240522.json - 用独立脚本(如 Python + jinja2 或 Node.js + handlebars)读取该 JSON,套用统一 Markdown 模板渲染
- 这样模板可由 SRE 团队直接修改,无需发版 Go 服务;也方便做 A/B 测试不同复盘格式
- 如果非要 Go 渲染,至少把模板文件外置,用
template.ParseFiles("report.md.tmpl"),别写死在代码里
最常被忽略的一点:复盘模板的生命力不在字段多寡,而在「每次填写是否真推动了改进」。比如 PreventiveAction 字段必须关联 Jira issue ID 或 GitHub PR URL,否则就是纸面流程。


















