👌

Go言語のバージョンアップ方法まとめ

2024/08/30に公開

はじめに

サービスのバックエンドにGoを使用しています。
最近、Goのバージョンが古くなってきたため、システムの安定性やセキュリティ、パフォーマンスを向上させるためにバージョンアップを行うことにしました。
本記事では、その手順と注意点について詳しく解説します。

結論から

Goは静的型付け言語であり、後方互換性を維持することを明言しています。
基本的な方針としては、まずバージョンを上げてみて、コンパイルエラーや実行時エラーが発生しないかを確認するのが最も効率的な方法です。

バージョンアップのコマンド

  • コンテナ、開発環境のgoバージョンアップ
    DockerfileのFROMを変更し、docker compose build --no-cache

  • go.modのバージョン変更

go mod edit -go=1.22.5
  • 依存関係のバージョン更新
go get -u ./...

バージョンアップによる影響確認

  • コンパイルエラーが無いかを確認
  • リリースノートを確認し、変更内容の中で挙動が変わりそうな実装がないかを確認
  • 実行時エラーが潜んでいるかもしれないため、念入りに動作確認しましょう

バージョンアップの詳細

バージョンアップの全体的な流れ

ローカル環境にて、アプリ用のDockerコンテナを起動し、その中で実行するアプリケーションのバージョンアップする想定で解説します。

  1. 現サービスのGoバージョンの確認
  2. goの最新リリース状況の確認
  3. ローカルのコンテナ内をバージョンアップ
  4. アプリケーションのバージョンアップ
  5. ローカル環境アップグレード

1. 現サービスのGoバージョンの確認

開発環境や実行環境にインストールされているGoのバージョンを確認します。

go version

go version go1.19.1 darwin/arm64

環境がDockerコンテナなどコンテナ化されている場合、DockerfileのFROMにバージョンが指定されているかと思います。

FROM golang:1.19.1 As builder

・・・

次にgo.modファイルに記載されているgoのバージョンを確認します。
3行目のgoで始まる部分がバージョンです。

module xxxxxxx/xxxxx/xxxxx

go 1.19.1

require (
    ・・・
}

2. goの最新リリース状況の確認

以下のページにはリリースされたバージョンが一覧で載っています。
リリースヒストリー
https://go.dev/doc/devel/release

このページから、各メジャーバージョン毎にそれぞれ個別のページに飛べるので、それぞれのバージョンでの変更点を確認しておきましょう。

例:go1.22のリリースノート
https://go.dev/doc/go1.22

メジャーバージョンにおける変更点は、パッケージ毎に変更された内容が記載されているので、アプリ内で使用しているパッケージについては特に変更点に注意しましょう。

また、各バージョンのマイナーリビジョンでの変更点については、最初に示したリリースヒストリーで確認が可能です。

例:go1.22のマイナーリビジョンの変更点
https://go.dev/doc/devel/release#go1.22.0

アップするバージョンの決定
Goは後方互換性を重視しているため、基本的には最新バージョンを選んで問題ないでしょう。
これまでの各バージョンのリリースノートの冒頭には、互換性がある旨が記載されています。
例えばv1.22であれば、以下のとおり

As always, the release maintains the Go 1 promise of compatibility. We expect almost all Go programs to continue to compile and run as before.
日本語訳:これまでどおり、このリリースでは Go 1の互換性が維持されています。ほぼすべての Go プログラムが、これまでどおりコンパイルおよび実行され続けることが期待されます。

ただし、goの不具合の修正などにより互換性を保てない修正も実際にあったりします。
このような場合の措置として新しいgoバージョンで古いバージョンのgoをコンパイルできる機能が組み込まれています。(go 1.21より正式採用されたGODEBUG機能)

https://go.dev/doc/godebug
https://go.googlesource.com/proposal/+/master/design/56986-godebug.md

3. ローカルコンテナのバージョンアップ

コンテナ定義の修正

localで起動するコンテナで使用
1行目のFROMを適切なバージョンのイメージに変更

FROM golang:1.22.5 As builder

コンテナのビルド、再起動
コンテナを再ビルドします。

通常のビルドではキャッシュが効いてしまうので、--no-cacheを付けて明示的にキャッシュを使用せずにビルドをします。

# コンテナビルド
docker compose build --no-cache

# コンテナ起動
docker compose up -d

4. アプリケーションのバージョンアップ

実行環境のGoのバージョンを上げたので、アプリケーションのバージョンを上げます。
以前はgo.modファイルのバージョンを書き換え、requireを全消ししてgo mod tidyしていましたが、
バージョンの更新や依存関係の更新用のコマンドがちゃんと用意されています。
https://go.dev/ref/mod#go-mod-edit
https://go.dev/ref/mod#go-get

go.mod

  • Goバージョンの更新

    go mod edit -go=1.22.5
    

    go.modに記載されているバージョン部分が変更されます。

  • 依存関係の更新

    go get -u ./...
    

    go get -u でgo.mod内のすべてのアップグレードができます。
    個別に特定のパッケージのみアップグレードしたい場合は、
    go get {パッケージ} とすることで1つずつアップグレードできます。

  • コンパイルエラーの確認

    go build ./...
    

    vscode等のエディタであればエラー箇所がわかるので事前に確認できるでしょう。
    コマンドで確認する場合はビルドでエラーが出てくれるでしょう。

5. ローカル環境アップグレード(Mac)

ローカルマシン上で開発する場合の環境のアップグレード方法について解説します。

  • homebrewの場合

    brew upgrade
    brew upgrade go
    
  • goコマンドの場合

    go install golang.org/dl/go1.22.5@latest
    ~/go/bin/go1.22.5 download
    

    通常のgoコマンドでは従来からインストールされているバージョンのgoが動作します。[1]
    go installでインストールしたgoを実行するためには以下のようにバージョン付きのコマンドで実行します。
    ~/go/bin/

    go version → 1.19.5が出力
    
    ~/go/bin/go1.22.5 version → 1.22.5が出力
    

    コマンドが長くなるため、ちょっと手間です。
    以下のようにGOROOTを差し替えると通常のgoコマンドで実行できそう

    export GOROOT=`~/go/bin/go1.22.5 env GOROOT`
    export PATH=$GOROOT/bin:$PATH
    go version
    
    go version go1.22.5 darwin/arm64
    

参考情報

Goの複数バージョンのインストールについて

https://go.dev/doc/manage-install
https://qiita.com/kane8n/items/83a9288927d968a8f695

go.mod関係

https://go.dev/ref/mod

goの互換性について

https://go.dev/doc/go1compat
https://go.dev/doc/godebug
https://go.googlesource.com/proposal/+/master/design/56986-godebug.md

リリースバージョン情報

https://go.dev/doc/go1.20
https://go.dev/doc/go1.21
https://go.dev/doc/go1.22
https://go.dev/doc/go1.23

脚注
  1. 複数のGoバージョンのインストールの詳細は公式のドキュメントを参考にしてください。
    https://go.dev/doc/manage-install#installing-multiple ↩︎

レスキューナウテックブログ

Discussion