一键导入
go-3am-debuggable
评审或新写 Go 代码时,用“凌晨 3 点能 debug”原则检查 panic stack 可读性、异步边界可见性、mock-only 间接层、callback 参数、闭包链、隐藏 goroutine 和单 caller 包装。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
评审或新写 Go 代码时,用“凌晨 3 点能 debug”原则检查 panic stack 可读性、异步边界可见性、mock-only 间接层、callback 参数、闭包链、隐藏 goroutine 和单 caller 包装。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when the user asks to correct English prompts, broken English, typos, grammar, wording, tone, workplace English, business writing, presentation language, or asks for English practice, quizzes, or help expressing ideas clearly in English.
Use when 用户要求提取、提炼、总结某个日期或时间范围的群聊/聊天记录(EACC 投资群 / eacc-chat),生成群聊日报、核心话题分析或投资价值信息筛选。触发词:提取聊天记录、群聊提炼、群聊总结、某月某日群里聊了什么、chat digest、群聊日报、群聊干货。
评估或对比会议纪要/访谈整理/深度纪要的质量:对照原始转录核查保真度,盘点覆盖度,输出多维度打分与失真清单。适用时机:(1) 用户问"这两份纪要哪份质量更高/写得更好",(2) AI 生成的纪要发布前验收(有没有幻觉、编造、立场写错),(3) 给纪要挑毛病/做质检/打分。触发语:评估纪要质量、对比纪要、纪要靠谱吗、纪要验收、纪要打分、哪份纪要好。
对会议纪要/活动回顾/访谈整理等将对外发布的文档做敏感信息检查与脱敏,覆盖查塔姆宫规则(Chatham House Rule)合规:人名机构名及变体、职级暗示、玩笑话与人事信号、点评同行、口语化敏感词、外链击穿匿名、身份指纹拼图、第三方未公开信息、编辑残留。适用时机:(1) 纪要将对外发布/进知识库/发群前,(2) 嘉宾或机构方要求脱敏审稿,(3) 用户提到查塔姆规则/讲事不讲人/匿名化/敏感信息检查。输出违规清单+修复建议,或直接执行脱敏。
Use when designing or reviewing lifecycle status fields, finite state machines, async task/order/payment/upload/approval workflows, or when states are overlapping, action-shaped, ownerless, unsafe under retries, concurrency, timeouts, or terminal-state updates.
深度研究与验证技能:当用户提出需要多源信息搜集、逻辑推理和事实验证的复杂问题时使用。 适用场景包括但不限于:投资研究、行业分析、技术对比、政策解读、商业决策支持等需要 "先想清楚怎么查,再去查,查完还要验证"的场景。 触发关键词/短语:为什么A而不是B、分析一下、帮我研究、设计一个SOP流程来回答、 深度分析、请验证、fact check、多角度分析、请先理解问题再回答、不要立即回答。 当用户明确要求"先设计研究流程再回答"或"验证你的结论"时,务必使用此技能。 当用户的问题涉及多个实体的比较(公司、技术、政策等)且答案不是简单事实时,也应触发。
| name | go-3am-debuggable |
| description | 评审或新写 Go 代码时,用“凌晨 3 点能 debug”原则检查 panic stack 可读性、异步边界可见性、mock-only 间接层、callback 参数、闭包链、隐藏 goroutine 和单 caller 包装。 |
代码的真正成本在凌晨 3 点告警响的时候。 每加一层间接,stack trace 多一帧 func1.func2,半夜你不知道哪一帧是你的。"灵活"和"可调试"经常冲突。
本 skill 只看一件事:这段 Go 代码会不会让维护者在压力状态下看不清调用关系、异步归属、错误归属或 panic 栈帧。
不要把本 skill 扩成通用 Go review checklist。除非它们直接造成下面的 3AM 失败面,否则不输出这些问题:
%w 错误包装建议、table test 风格、exported API 文档、package 分层这些可以属于另一个 go-maintainability-review skill;这里默认不报。
看到 helper、closure、callback、goroutine、mock seam 时先问:
func1.func2?| Tier | 含义 | 处理 |
|---|---|---|
| T1(硬性,必清) | 直接破坏 stack trace、异步可见性、错误归属、测试结构 | 看到就改。问"怎么改成本最低",不问"要不要改"。 |
| T2(应修) | 削弱压力状态下的扫读和改动安全,但 panic 栈仍基本可读 | 默认应改。保留时说明真实收益和代价。 |
不要引入 Blocker/Major/Minor/Nit 另一套等级;本 skill 只用 T1/T2。
panic 栈、火焰图、debugger 单步都依赖函数名。.func1.func2.func3 这种栈帧名半夜读不懂。
具体禁止:
func(...) { ... func(...) { ... } }a := func(...)、b := func(...),且 b 内部调 atrpc.Go(ctx, t, func(ctx){ ... someFn(func(){...}) })err 变量等单个局部 closure 本来是 T2;一旦它链到另一个 closure、藏住异步归属、或捕获会跨 caller 生命周期的可变状态,升级为 T1。
修法优先级:统一控制流消掉 helper 理由 → 内联 → 提成具名函数 → 抽 builder struct/method。struct 是 fallback,不是第一反应。
go func、trpc.Go、errgroup.Go 必须出现在 caller 函数体里,或被一个名字明确的 Async / Go / Background helper 包住。caller 不能误以为这是同步函数。
// ✅ caller 一眼看见异步边界
trpc.Go(ctx, 5*time.Second, func(ctx context.Context) {
reportXxx(ctx, groups)
})
// ❌ 异步藏在普通 helper 里
reportXxx(ctx, groups) // 内部偷偷 trpc.Go
异步边界还必须交代归属:
禁止在 request-scoped async work 中随手改成 context.Background() / context.TODO(),这会切断 trace、deadline、鉴权、cancel。只有明确 detach 的后台任务可例外,名字或注释要写出 owner 和 timeout,例如 startBackgroundReport...。
允许的例外:helper 名字含 Async / Go / Background,且 helper 内部不再接 func() 参数;否则会叠加 #1 和 #4。
项目用 bytedance/mockey 时,runtime 可以直接 patch 包函数、method、闭包。禁止这种纯测试壳:
// ❌ 反例(mock-only fake seam)
var (
reportLogFunc = tlog.ReportLog
trpcGoFunc = trpc.Go
buildGroupsFunc = buildGroups
)
直接 mockey.Mock(tlog.ReportLog).To(...).Build()。每多一个 xxxFunc 包装,读者都要猜"这是真函数还是测试钩子?"。
唯一豁免:mock 目标是 method value 且对象尚未实例化,必须提前替换。其他一律删。
传数据,不传 closure。
// ❌ caller 把"怎么造数据"包成 closure 传进去
func reportAsync(ctx context.Context, buildFn func() []Group) { ... }
// ✅ caller 自己造好或在可见的 goroutine body 里造好,再传数据
func reportAsync(ctx context.Context, groups []Group) { ... }
豁免只有两个:
"想让构造也在 goroutine 里跑"不算豁免;把构造代码写进 caller 可见的 goroutine body 即可。
包级 helper 只有 1 个生产调用点时,通常是过度提取。inline 它,等真有第二个 caller 再抽。
豁免:API handler、cron entrypoint、接口实现、测试入口等天然入口,即使单 caller 也合理。
xxx := func(...) {...} 把闭包赋给变量,panic 栈帧显示 .func1 而非 xxx。
修法优先级:
同一函数出现 2 个以上局部 closure 时,必须检查是否互相调用;互调就是 T1 #1。
两个 caller 共享 5 行 trpc.Go(ctx, timeout, func(ctx){...}) 壳子时,复制通常比抽 helper 好。
抽象阈值:至少 3 个 caller,且共用逻辑不少于 10 行有意义代码。低于这个阈值,优先复制;复制的两份可以独立演化,抽象会把读者拖进 callback/helper 调用图。
不要先把闭包机械改成 struct method。先问:
helper 是否只是因为外层分支太多?能不能把分支归一成数据,再用一个主循环处理?
典型 pattern:多分支都是"对某个名字 ensure + append"。先把目标名归一成 dests []string,再统一进入 for _, dest := range dests。这样 helper 往往直接消失。
如果读者必须在长函数里追踪多个 map/slice/index 的远距离变更,或多个分支各自偷偷改同一组 accumulator,这也是 T2。修法仍然是:归一数据和控制流 > 内联 > 具名函数 > struct method。
满足下面两条的匿名 func 是 Go 生态标准用法,不算反模式:
trpc.Go(ctx, t, func(ctx){...})、sort.Slice(s, func(i,j int) bool{...})、sync.Once.Do(func(){...})、http.HandleFunc(...)例子:
sort.Slice(items, func(i, j int) bool {
return items[i].Score > items[j].Score
})
先写直白的同步扁平版,真有 3+ caller 才抽公共函数。
trpc.Go / go func / errgroup.Gofunc() T 参数、xxxFunc = realFn、局部 xxx := funcctx、吞 error、捕获可变 statebash scripts/scan.sh <go-dir>,把输出当作可疑线索,不当 gate按 Tier 输出,不空谈:
review 时每个 finding 至少包含:
不要输出只有"建议优化""可以更清晰"这类没有 3AM 失败面的泛泛意见。
bash scripts/scan.sh <go-dir> — 启发式扫描,始终退出 0:
var xxxFunc = realFnfunc() Tcontext.Background/TODO 线索中心思想来自 Go 文化里的 clarity > cleverness、explicit > magic,但本 skill 只保留会影响 3AM 调试的部分。