资讯动态

oh-my-pi 内置规则 go-add-cleanup 解析:Go 1.24 下用 runtime.AddCleanup 替代 SetFinalizer 的迁移指南

发布时间:2026/9/11 2:01:44 来源:尧图企业网站定制
oh-my-pi 内置规则 go-add-cleanup 解析Go 1.24 下用 runtime.AddCleanup 替代 SetFinalizer 的迁移指南【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi本篇指南围绕 oh-my-pi 编码代理coding-agent内置的 TTSRTool-Time Self-Reflection工具调用时自省规则go-add-cleanup展开它是随仓库分发的一组内置默认规则builtin rules之一用于在 Agent 编辑或写入*.go文件时一旦检测到runtime.SetFinalizer调用便主动引导代码迁移到 Go 1.24 新增的runtime.AddCleanup。读完本文你将掌握AddCleanup相对SetFinalizer的优势、完整的迁移写法与参数约束、何时必须保留SetFinalizer以及这条规则在 oh-my-pi 中是如何被解析、注册、命中与覆盖的完整链路。规则文件速览一条规则由什么组成规则本体位于 go-add-cleanup.md文件开头是一段 YAML frontmatter声明了规则的类型、触发条件与作用范围--- description: Prefer runtime.AddCleanup over runtime.SetFinalizer for new code (Go 1.24) condition: runtime\.SetFinalizer scope: tool:edit(*.go), tool:write(*.go) interruptMode: never ---四个字段的含义与底层映射如下对应 rule.ts 中RuleFrontmatter与Rule的定义description规则的语义描述进入 rulebook规则手册时作为该条目的摘要文本便于 Agent 按需检索引用condition一个 PCRE 风格正则runtime\.SetFinalizer作为 TTSR 触发条件——当工具输出流中出现匹配该正则的文本时触发规则注入详见后文规则的 TTSR 注册与匹配一节scope规则的流作用域tool:edit(*.go), tool:write(*.go)表示仅在edit/write这两个工具处理*.go文件时才参与匹配不会在普通文本讨论中被误触发interruptMode: never中断模式为never即该规则命中后仅注入参考内容、不打断 Agent 的工具执行流合法取值还包括prose-only、tool-only、always见 rule.ts。正文则是一句话的规则结论Go 1.24 新增了runtime.AddCleanup新代码应当优先使用它而不是runtime.SetFinalizer。为什么 AddCleanup 更优四个决定性差异规则文档给出了AddCleanup胜出的四个技术理由这也是迁移决策的完整依据一个对象可挂多个 cleanupSetFinalizer只能挂一个。runtime.SetFinalizer对每个对象只允许注册一个终结器后注册的会覆盖先前的而AddCleanup允许为一个对象注册多个清理函数各自携带独立的参数适合一个对象同时持有文件描述符、缓冲区、子资源等需要多路释放的场景。cleanup 可以附着在内部指针interior pointer上。例如结构体字段、切片元素的指针这在SetFinalizer下是被 Go 运行时明确拒绝的SetFinalizer要求指针指向堆分配对象的起始位置。存在引用循环时cleanup 照常运行而 finalizer 会泄漏。被SetFinalizer标记的对象若处于无法单独回收的引用环中其终结器可能永远不会被调度资源随之泄漏AddCleanup不依赖对象整体不可达这一前置条件循环场景下仍能执行清理。cleanup 既不会复活对象也不会让对象或其引用多存活一个 GC 周期。SetFinalizer存在两类知名陷阱终结器可以把对象重新变为可达复活resurrect且终结器运行后对象通常还要再等一个 GC 周期才被真正回收AddCleanup从机制上消除了这两类延迟与不确定性。需要说明以上四点均直接继承自规则文档原文属于官方 Go 1.24 标准库行为与规则制定依据的转述不涉及本仓库自行声明的性能数据。迁移示例与参数约束写对 AddCleanup 的关键规则文档给出了改造前后的最小对照代码这也是 Agent 在检测到runtime.SetFinalizer时会被引导产出的标准形态// Before runtime.SetFinalizer(obj, func(o *T) { o.release() }) // After — the cleanup func receives a value you supply, NOT the object, // so it cannot accidentally keep the object alive. runtime.AddCleanup(obj, func(h handle) { h.release() }, obj.handle)逐行拆解这段迁移代码的语义obj仍是宿主对象GC 判定obj不再可达后注册的 cleanup 才会被调度与SetFinalizer不同AddCleanup的清理函数参数由调用方显式传入此处为obj.handle一个handle值而不是回调里重新引用obj本身正是参数由你提供、而非对象本身这一点从源头杜绝了回调把obj意外保活keep-alive的可能。规则文档随后给出了一条强制约束迁移时必须遵守Cleanup 参数不得引用obj自身否则obj将永远可达remain reachable forevercleanup 永远不会被触发。应只捕获必要的数据文件描述符file descriptor、句柄handle或与obj生命周期无关的指针。这是AddCleanup最容易踩的坑回调参数一旦间接携带对宿主对象的引用就等价于给对象续了永久的可达性清理逻辑形同虚设。因此合理的参数选择是可独立完成释放动作的最小资源句柄而不是对象本身或其内含的可达引用链。何时必须继续使用 SetFinalizer规则文档明确了两类例外场景这两类情况下不强制迁移模块目标 Go 版本低于 1.24。runtime.AddCleanup是 Go 1.24 才引入的 APIgo.mod中go指令低于 1.24 的模块无法直接调用此时只能沿用SetFinalizer确实需要 finalizer 专属行为最典型的是对象复活resurrection——AddCleanup不提供复活能力若代码依赖终结器把对象重新置回可达状态则必须保留SetFinalizer。除此之外的新代码规则的建议是统一迁移到runtime.AddCleanup。规则的 TTSR 注册与匹配Agent 如何看见这条规则理解了规则语义后再看它如何进入 Agent 的运行管线。规则定义集中在 builtin-rules/index.ts这里通过with { type: text }静态导入把 Markdown 原文嵌入二进制并注册为一个名为go-add-cleanup的规则源BUILTIN_RULE_SOURCES。注释明确指出这样嵌入的目的是让bun build --compile产出的二进制自带这些规则不依赖外部的松散规则文件。随后 builtin-defaults.ts 以builtin-defaults为 provider id、PRIORITY 1全仓库最低优先级注册这批规则buildRuleFromMarkdown负责把 frontmatter 正文解析成规范的Rule对象解析逻辑见 helpers.ts 的buildRule。低优先级的意义在于任何用户、项目或工具来源的同名规则都能覆盖这份内置副本内置规则只是兜底默认值。规则进入会话后由 rule-buckets.ts 的bucketRules统一分桶处理命中顺序如下disabledRules中列出的规则名直接丢弃ttsr.builtinRules false时丢弃全部builtin-defaults来源的规则agents作用域不匹配当前 Agent 名的规则被丢弃具有非空condition/astCondition的规则交给TtsrManager.addRule注册为 TTSR 规则——go-add-cleanup正是这一类其condition: runtime\.SetFinalizer会被编译为RegExp参与流匹配compileRuleCondition还支持(?i)这类行内旗标的转换见 rule.ts其余按alwaysApply与description落入 always-apply 或 rulebook 桶。因此当 Agent 在edit(*.go)/write(*.go)的工具输出中写下runtime.SetFinalizer时go-add-cleanup规则即被命中注入引导 Agent 按上文迁移范式改写为runtime.AddCleanup。开关与验证按需关闭、单独禁用与本地调试内置规则并非不可关闭。在 settings-schema.ts 中定义了两个用户可配置项ttsr.builtinRules布尔值默认true置为false则整批丢弃内置默认规则ttsr.disabledRules字符串数组默认[]可单独列出规则名以忽略某一条对内置规则与用户自己的规则均生效。例如只想关掉go-add-cleanup而保留其他 Go 内置规则只需在配置的ttsr.disabledRules中加入go-add-cleanup若希望自定义一份更严格的版本则可在更高优先级来源中定义同名规则覆盖内置副本。调试与验证方面仓库提供omp ttsr命令族见 ttsr-cli.tsomp ttsr list列出当前项目/用户已注册的全部 TTSR 规则包括规则名与命中条件可用于确认go-add-cleanup是否加载omp ttsr scan对指定文件/片段执行扫描展示哪些规则会被命中omp ttsr test给定代码片段与--source/--tool等上下文评测规则实际触发情况——例如可以用一段含runtime.SetFinalizer的 Go 片段验证命中再验证迁移为runtime.AddCleanup后不再命中。结语go-add-cleanup是 oh-my-pi 内置规则体系中语言惯例 TTSR 流内注入模式的典型样本以极小的 Markdown 文件承载一条精确的工程约定Go 1.24 下优先runtime.AddCleanup通过 frontmatter 声明条件与作用域由低优先级 provider 兜底分发并允许用户通过ttsr.builtinRules/ttsr.disabledRules或同名规则覆盖。对 Go 开发者而言理解这条规则的语义即可直接复用其迁移范式对希望为团队定制同类规则的读者则可以把本仓库的 builtin-rules 目录当作一份可直接参考的模板集。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价