关于 go-fix
使用 Go 1.26 及更高版本的 `go fix` 现代化 Go 代码的工作流技能。它先检查工具链与仓库前提,再预览并应用符合模块版本的重写,最后验证构建和测试。
主要功能
- 01要求 Go 1.26 或更高版本
- 02检查模块与干净的 git 状态
- 03预览并应用安全重写
- 04重复修复直至无待处理项
- 05验证构建与测试
- 06支持单项分析器运行及 CI 检查
适用场景
- 01在不超出模块声明 Go 版本的前提下现代化代码
- 02应用自动重写前审查变更
- 03分批运行指定分析器修复以便审查
- 04在 CI 中检查现代化差异且不写入文件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rshade/ agent-skills --skill go-fix安装后在 Claude Code 中输入/go-fix确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonevals/fixture-old/go.modmain.goevals/fixture/generated.gogo.modmain.goreferences/analyzers.md详细介绍
Go 修复
使用 go fix 现代化 Go 代码。它基于 Go 分析框架,在 Go 1.26 中重建。它会安全地将代码重写为更新的语言和标准库惯用写法,同时遵守模块声明的 Go 版本——绝不会将代码重写为模块尚未通过 go.mod 启用的特性。
此技能的作用
- 验证工具链为 Go 1.26 或更高版本;否则停止。
- 检查前置条件:Go 模块和干净的 git 状态。
- 使用
go fix -diff预览修复并应用,然后反复运行,直到没有剩余修复(修复可能会暴露更多修复)。 - 验证结果能够构建且测试通过,然后报告所做的更改。
工具链检查(必需——不得跳过)
现代化工具仅存在于 Go 1.26 及更高版本中。在较旧的工具链上,go fix 是旧版工具:它会运行,但找不到任何内容,并正常退出——这看起来像是“代码已经现代化”,实际却是“工具链错误”。务必先检查:
if [ "$(printf '%s\n' go1.26 "$(go env GOVERSION)" | sort -V | head -n1)" != "go1.26" ]; then
echo "go fix modernizers require Go 1.26+, found $(go env GOVERSION)" >&2
exit 1
fi
如果工具链版本过旧,请停止并提供升级指引(https://go.dev/dl/)。不要悄悄运行旧版修复工具。
前置条件
- Go 模块:工作目录中或其上级目录中必须存在
go.mod。 - 干净的 git 状态:要修复的文件应满足
git status --porcelain输出为空,这样重写才能作为独立且便于审查的更改提交。如果工作区有未提交更改,请先询问,或先提交 / 暂存。 - 记录模块的
go指令:修复受它控制。声明go 1.21的模块会进行any和strings.Cut重写,但不会进行range n(1.22)或new(expr)(1.26)重写。除非用户明确要求,否则绝不要仅为启用更多修复而提升go指令。
工作流
1. Toolchain check
├─ go env GOVERSION >= go1.26 → continue
└─ older → stop, report upgrade guidance
2. Preconditions
├─ go.mod present, git state clean → continue
└─ dirty tree → ask / stash first
3. Preview
└─ go fix -diff ./...
├─ exit 0 → nothing to do, report "already modern"
└─ exit 1 → diff printed; review it, then apply
4. Apply to fixed point (cap at ~4 passes)
└─ go fix ./... ; repeat while go fix -diff ./... exits 1
5. Verify
├─ go build ./... && go test ./...
└─ failures are rare semantic conflicts → fix by hand, report
6. Report
└─ analyzers that fired, files touched, behavior-change flags
运行方式
完整现代化至固定点
go fix -diff ./... # preview; exit 1 means fixes are available
go fix ./... # apply
go fix -diff ./... # re-check: some fixes expose more fixes
重复应用和检查,直到 -diff 以 0 退出。通常两轮就足够(例如,minmax 首先将夹值操作简化为 max(...),然后在下一轮简化为 min(max(...), ...))。
每次运行一个分析器(PR 更小,也更易审查)
go fix -newexpr ./... # run only newexpr
go fix -any=false ./... # run everything except any
完整运行会触及许多文件时,优先使用此方式——每个提交只运行一个分析器,以便于审查。
CI 检查(不写入文件)
有可用修复时,go fix -diff 会以非零状态码退出,因此可以像 gofmt -l 一样用作检查步骤:
go fix -diff ./... # exit 0 = modern, exit 1 = drift (diff printed)
带构建标签的代码
go fix 会分析当前平台的文件集。对于受构建标签控制的代码,请按平台分别运行:
GOOS=linux GOARCH=amd64 go fix ./...
GOOS=darwin GOARCH=arm64 go fix ./...
安全与审查说明
- 会自动跳过生成文件(
// Code generated ... DO NOT EDIT.)——应修复生成器。 - 大多数修复器都能保持行为不变,但请重点审查以下两项:
- omitzero:对于结构体类型的 JSON 字段,将
omitempty替换为omitzero会改变行为(零值结构体会被省略)。它会跳过带有+kubebuilder注释的包。 - mapsloop:重写为
maps.Clone会保留源映射是否为 nil,这可能与始终分配新映射的循环不同。
- omitzero:对于结构体类型的 JSON 字段,将
- 独立修复之间罕见的语义冲突会在应用后表现为编译错误——这就是第 5 步要构建和测试的原因。请手动解决;不要指望重新运行
go fix能自动修复。
报告格式
go fix report (go1.26.4, module go directive: 1.26)
Pass 1: 12 fixes across 5 files
any (3), rangeint (4), stringscut (2), newexpr (3)
Pass 2: 1 fix (minmax collapsed to min(max(...)))
Pass 3: clean (go fix -diff exits 0)
Verify: go build ./... OK, go test ./... OK
Review flags: none (omitzero/mapsloop did not fire)
如果没有触发任何修复,请报告工具链版本、模块的 go 指令,并说明该版本对应的代码已经现代化——同时指出,如果用户希望启用更多修复,可以提升 go 指令。
分析器参考
请参阅 references/analyzers.md,了解全部 22 个分析器、每种重写所针对的最低 Go 版本、各分析器示例、标志,以及库作者如何使用 //go:fix inline 发布自己的迁移。