go-fix について
Go 1.26 以降の `go fix` で Go コードを近代化するワークフロースキルです。ツールチェーンとリポジトリの前提条件を確認し、モジュールの Go バージョンに合う修正を適用した後、ビルドとテストを検証します。
主な機能
- 01Go 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 Fix
Go 1.26 で再構築された、Go Analysis フレームワーク上の go fix を使って、Go コードをモダナイズします。モジュールで宣言された 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の出力が空である必要があります。これにより、書き換えが単独でレビュー可能な変更になります。作業ツリーに変更がある場合は、続行する前に確認するか、先にコミットまたは stash してください。 - モジュールの
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 を返すまで、適用と確認を繰り返します。通常は 2 回のパスで十分です(例:minmax は最初にクランプ処理を max(...) にまとめ、次のパスで min(max(...), ...) にします)。
アナライザーを 1 つずつ実行する(小規模でレビューしやすい PR)
go fix -newexpr ./... # run only newexpr
go fix -any=false ./... # run everything except any
全体を実行すると多くのファイルに変更が及ぶ場合は、この方法をおすすめします。コミットごとにアナライザーを 1 つにすれば、レビューしやすくなります。
CI ゲート(書き込みなし)
修正がある場合、go fix -diff は 0 以外で終了するため、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.)は自動的にスキップされます。代わりにジェネレーターを修正してください。 - 多くの修正ツールは動作を維持しますが、次の 2 つは特に注意してレビューしてください。
- 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 を使って独自の移行を公開する方法が記載されています。