mcpField
G
go-fix

go-fix

github.com/rshade开发339 次安装1 周前更新
代码仓库

关于 go-fix

使用 Go 1.26 及更高版本的 `go fix` 现代化 Go 代码的工作流技能。它先检查工具链与仓库前提,再预览并应用符合模块版本的重写,最后验证构建和测试。

主要功能

  1. 01要求 Go 1.26 或更高版本
  2. 02检查模块与干净的 git 状态
  3. 03预览并应用安全重写
  4. 04重复修复直至无待处理项
  5. 05验证构建与测试
  6. 06支持单项分析器运行及 CI 检查

适用场景

  1. 01在不超出模块声明 Go 版本的前提下现代化代码
  2. 02应用自动重写前审查变更
  3. 03分批运行指定分析器修复以便审查
  4. 04在 CI 中检查现代化差异且不写入文件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rshade/agent-skills --skill go-fix

安装后在 Claude Code 中输入/go-fix确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
evals/fixture-old/
go.mod
main.go
evals/fixture/
generated.go
go.mod
main.go
references/
analyzers.md

详细介绍

Go 修复

使用 go fix 现代化 Go 代码。它基于 Go 分析框架,在 Go 1.26 中重建。它会安全地将代码重写为更新的语言和标准库惯用写法,同时遵守模块声明的 Go 版本——绝不会将代码重写为模块尚未通过 go.mod 启用的特性。

此技能的作用

  1. 验证工具链为 Go 1.26 或更高版本;否则停止。
  2. 检查前置条件:Go 模块和干净的 git 状态。
  3. 使用 go fix -diff 预览修复并应用,然后反复运行,直到没有剩余修复(修复可能会暴露更多修复)。
  4. 验证结果能够构建且测试通过,然后报告所做的更改。

工具链检查(必需——不得跳过)

现代化工具仅存在于 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,这可能与始终分配新映射的循环不同。
  • 独立修复之间罕见的语义冲突会在应用后表现为编译错误——这就是第 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 发布自己的迁移。

评论

支持 Markdown