every Tech Blog

株式会社エブリーのTech Blogです。

Go 1.26で変わるgo fix

記事サムネイル
Go 1.26で変わるgo fix

この記事は every Tech Blog Advent Calendar 2025 の 26 日目の記事です。

はじめに

開発本部でデリッシュキッチンアプリ課金ユーザー向けの開発を担当しているhondです!
先日2026年2月にリリース予定のgo1.26のRelease Candidate 1であるgo1.26rc1がリリースされました。もうrc1は確認できたでしょうか?確認がまだの方はこちらから確認できるのでぜひ!
今回はGo 1.26でgo fixが大幅に変更されるとのことだったのでそちらについて説明しようと思います。

go fixとは

go fixはGo 1リリースにて破壊的変更を含む古いAPIを特定し、新しいものに修正するツールとして追加されました。 go fixによって大まかな修正はできるため、私たちはコアな部分の修正に集中できるようになっていました。
Go 1リリースの際はgo fixでの修正対象は多くGo 1のRelease NotesUpdating: Running go fixと調べるだけでも14件ヒットし、ソースコードを確認すると37件ものルールがあることが確認できます。その後もgo fixのルールは追加削除が繰り返されていきましたが、Goがメジャーバージョン内での後方互換性を担保しているので最近はなかなか変更が行われず使わないコマンドとなっていました。

Go 1.26での変更点

github.com

Go 1.26ではcmd/go: fix: apply fixes from modernizers, inline, and other analyzersにてgo fixが大幅に変更される旨のProposalがAcceptされました。

この変更の背景は、元のissueであるcmd/fix: remove all functionalityとGopherCon 2025でのAlan Donovanの発表(Analysis and Transformation Tools for Go Codebase Modernization)から確認できます。具体的には以下の3点が挙げられています。

  • 「go fixとは」でも触れた既存go fixの機能であるcontextbuildtagの修正が不要になったこと
  • コードレビュー時間の短縮や開発者の教育のためにモダン化が必要だったこと
  • AI/LLMが生成するコードの品質改善のためにモダン化が必要だったこと

これらの背景を踏まえ、modernize//go:fix inlineのようなGoのコードのモダン化を目的とするアナライザーをgo vet同様にgo fixでも利用可能にすることがこのProposalの目的となっています。
go vetgo fixの使い方は似ていますが、あくまでgo vetはアナライザーを用いて静的解析した診断結果を報告するツール、go fixは検出した問題をアナライザーが提案する修正案に修正するツールという使い分けになるようです。

以降では、Go 1.26のgo fixで利用可能になるmodernizeinlineについて詳しく説明します。

modernizeとは

pkg.go.dev

modernizegolang.org/x/tools/go/analysis/passes/modernizeで公開されているアナライザーのスイートです。Goのコードを最新の構文や標準ライブラリの機能を利用して、より簡潔でモダンな形式に修正することを目的としています。

現在24個のアナライザーが登録されており、その中から代表的なものを紹介します。Go 1.26で追加されるerrors.AsTypeのアナライザーも既に登録されています!

Analyzer 説明
any interface{}anyに修正する
errorsastype errors.AsをGo 1.26で追加されたerrors.AsTypeに修正する

使い方

以下のコマンドでmodernizeを実行することができます。

$ go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix ./...

また、特定のアナライザーを有効・無効化することも可能です。

# anyアナライザーを有効化
$ modernize -any=true -fix ./...

# anyアナライザーを無効化
$ modernize -any=false -fix ./...

基本的には修正を適用しても動作が変わらないよう設計されていますが、bloopのように完全に動作を保証できないアナライザーもあり、それらはデフォルトでは無効化されています。

実行例

以下では実際にanyアナライザーを使ってinterface{}anyに修正してみます。

修正前のコード:

package main

import "fmt"

type OldInterface interface{}

func main() {
    old := OldInterface(1)
    fmt.Println(old)
}

コマンド実行:

$ go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix ./...

出力(差分):

 import "fmt"
 
-type OldInterface interface{}
+type OldInterface any
 
 func main() {
        old := OldInterface(1)

このように、interface{}anyに自動で修正されたことが確認できます。

inlineとは

pkg.go.dev

inlinegolang.org/x/tools/go/analysis/passes/inlineで公開されているパッケージで、inlinegofixdirectiveの2つのアナライザーが含まれています。

inlineアナライザーは//go:fix inlineコメントディレクティブに基づいて修正を行います。主に非推奨になった関数や定数を新しいものに置き換えるために使用され、ioutil packageなどで利用されています。

具体的な使い方は以下の通りです。

  • 関数の場合:修正したい関数をラップした関数を作成し、その関数にコメントディレクティブを加えることで修正が可能です。
//go:fix inline
func Square(x int) int { return Pow(x, 2) }
  • 定数の場合:修正したい変数を左辺に、修正後の変数を右辺に記述し、コメントディレクティブを加えることで修正が可能です。
//go:fix inline
const Ptr = Pointer

使い方

以下のコマンドでinlineを実行することができます。

$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...

また、goplsを用いているIDE上では対象をホバーすることでも修正が可能です。

実行例

以下では、OldFunctionNewFunctionを定義し、OldFunctionNewFunctionに修正する際の例を示します。

修正前のコード:

package main

import "fmt"

func main() {
    OldFunction()
    NewFunction()
}

//go:fix inline
func OldFunction() {
    NewFunction()
}

func NewFunction() {
    fmt.Println("NewFunction")
}

コマンド実行:

$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...

出力(差分):

 import "fmt"
 
 func main() {
-       OldFunction()
+       NewFunction()
        NewFunction()
 }

このように、OldFunctionNewFunctionに修正されるのが確認できます。

IDEでの修正

コマンドを使わずに、IDE上で対象をホバーすることでも修正が可能です。

IDEでホバーした時の画像

Quick Fixを選択すると、修正候補が表示されクリックすることで修正が可能です。

Quick Fixを押した時の表示

新しいgo fixでできること

ここまで説明したmodernizeinlineは、Go 1.26からはgo fixを実行するだけで適用できるようになります。今までは破壊的変更を修正するためのツールだったgo fixが、Goのコードをモダン化していくためのツールへとシフトしました。

実際にgo1.26rc1を使ってgo fixを実行してみます。

$ go1.26rc1 fix ./...

modernizeの結果:

 import "fmt"
 
-type OldInterface interface{}
+type OldInterface any
 
 func main() {
        old := OldInterface(1)

inlineの結果:

 import "fmt"
 
 func main() {
-       OldFunction()
+       NewFunction()
        NewFunction()
 }

このように、go fixを実行するだけでコードをモダン化された状態に持っていくことができます。コード品質の担保がより容易になるため、pre-commitフックやCI、AI/LLMの出力後に適用するルールとして定義するのが良さそうです!

まとめ

私自身go fixを使う機会がなかったので、今回のアップデートで既存のgo fixとモダン化の為のツールとして進化したgo fixを会社のコードに適用するいい機会になりました。既存のgo fixでの修正点は一部のcontextのみでしたが、新しいgo fixを実行したところ1249の修正点が確認されました。10年もののサービスという事もありこれらのコードを全て手動で特定し、修正していくとなると莫大な労力を要するので公式からこのようなツールが出ていることはとても有り難いなと思いました。
上記で修正されたのはmodernizeに定義されたアナライザーやそれぞれのpackageにて//go:fix inlineが定義されているものですが、//go:fix inlineに関しては普段の開発でも非推奨化したがバージョン互換性担保の観点で削除できないコードを管理する際にとても有用なので積極的に利用して行きたいです。
AIはどうしても既存のコードベースに品質が左右されてしまうので新しくなったgo fixを用いて、継続的な品質改善が重要だと感じました。また、公開されたコードベースを元にAIは学習していくので今後の自分を含めたGopherがAIを通してより良いコードを書くためにも積極的にモダン化を行おうと思います。
ここまで読んでいただきありがとうございます。Go 1.26でgo fixがどう変わるか迷っている方の助けになれたら幸いです!