Goプロジェクトのバージョンを上げる3ステップ(go.mod・Dockerfile・ローカル環境)

Goプロジェクトのバージョンを上げる3ステップ(go.mod・Dockerfile・ローカル環境)

6分で読めるテック
最終更新:

既存のGoプロジェクトのバージョンを上げる際、自分は最初 go.mod だけ変えれば済むと思っていました。実際には go.mod・Dockerfile・ローカル環境の3か所を合わせて変更しないとビルドやローカル動作がちぐはぐになります。作業を通して整理した手順をまとめます。

Goのサポートポリシーを確認する

どのバージョンに上げるかを決める前に、Goのサポートポリシーを確認します。Go言語は「最新の2メジャーバージョンまでをサポートする」という方針を採っています。

Each major Go release is supported until there are two newer major releases

つまり現時点でサポートされているのは最新2つのメジャーバージョンのみです。それより古いバージョンにとどまっているプロジェクトは、セキュリティパッチも当たらない状態になります。

もう一点、Go 1系の後方互換性ポリシーも確認しておきます。Go 1の範囲内であれば、古いバージョンで書いたコードは新しいバージョンでも正しくコンパイル・実行され続けることが意図されています。

このポリシーのおかげで、バージョンを上げても既存コードが動かなくなるリスクは比較的小さいです。念のためリリースノートでその間の変更点は確認するようにしています。

現在サポートされているバージョンは以下で確認できます。

ステップ1: go.modのバージョンを更新する

go mod edit コマンドで go.modgo ディレクティブを書き換えます。

go mod edit -go=1.23

コマンド実行後は go.mod の先頭付近にある go 1.xx の行が指定したバージョンに変わります。変更後は必ず go mod tidy を実行してモジュール依存関係を再解決します。

go mod tidy

go mod tidy はバージョン変更後に使われなくなった依存や、新しく必要になった依存を整理してくれます。これをスキップすると go.sum との不整合でビルドが失敗することがあります。

ステップ2: Dockerfileのイメージを更新する

Docker環境でビルドしている場合は、Dockerfile の FROM 行も合わせて変更します。go.modだけ変えてDockerfileをそのままにすると、ローカルとコンテナで異なるバージョンが動く状態になります。

FROM golang:1.23-alpine

-alpine を使っている場合はイメージサイズが小さいのでそのまま維持してよいですが、このタグの存在は Docker Hub で確認してから変更します。

ステップ3: ローカルのGoバージョンを揃える

ローカル環境のGoバージョンが古いままだと、go mod edit で指定したバージョンより古いGoで動かすことになり、新しい言語機能やツールチェーンとの差異が出ます。

mise を使っている場合は以下で更新できます。

mise use go@1.23

asdf を使っている場合は次のようになります。

asdf install golang 1.23
asdf local golang 1.23

バージョンマネージャを使っていない場合は公式サイトからインストールします。

ビルドと動作確認

3か所の変更が揃ったら、ビルドを通してエラーがないことを確認します。

go build ./...

テストがあれば合わせて実行します。

go test ./...

バージョン変更後に破壊的な変更が入っていないかはリリースノートで確認しておくと安心です。Go 1系の後方互換性ポリシーがあるとはいえ、ツールチェーン周りの挙動が変わることはあります。

よくある落とし穴

go.modとDockerfileのバージョンがずれる

go mod edit でgo.modを更新しても、CIや本番環境がDockerイメージで動いている場合はDockerfileを変えないとコンテナ内のGoバージョンが変わりません。「ローカルでは動くのにCIが失敗する」原因の多くはこのズレです。

go mod tidyで依存が消える

バージョンアップ後に go mod tidy を実行すると、新しいGoバージョンで不要になった依存が go.sum から消えることがあります。これは正常動作ですが、チームで開発している場合は go.sum の変更がコンフリクトしないよう、バージョンアップは1ブランチにまとめてPRを出す運用が無難です。

ツールチェーンディレクティブが追加される

Go 1.21以降、go.modtoolchain ディレクティブが追加されることがあります。

go 1.23.0
toolchain go1.23.4

これはビルドに使うツールチェーンのバージョンを固定するための記述で、Go 1.21から導入された機能です。go mod editgo mod tidy を新しいツールチェーンで実行すると自動的に追記されます。チームで使うGoのツールチェーンを固定したい場合は役立ちますが、想定外の記述が増えて混乱することもあります。

リリースノートの確認方法

バージョンアップ前後のリリースノートを確認するのが安全です。

Go のリリースノートは言語変更・標準ライブラリの変更・ツールチェーンの変更・パフォーマンス改善のセクションに分かれており、どこを重点的に読めばよいかわかりやすく整理されています。GODEBUG 環境変数で旧来の挙動に戻せるケースも記載されているため、動作が変わった場合の調査起点としても使えます。

質問・リクエストを送る

記事についての質問や、取り上げてほしいテーマがあればお気軽にどうぞ。いただいた質問はブログ記事として回答し、Q&Aページで公開することがあります。

このサイトについて

井上 周(Amane Inoue)の個人ブログです。技術・読書・ドラマ・旅・大学生活のことを書いています。