Go言語のホットリロードツール『Air』でコードの修正を即時反映させる

Go言語

ホットリロードを導入することで開発の作業効率の向上が期待できます。

Go言語のホットリロードツールではRealizeAirが有名です。
しかし2021年5月現在、Realizeはdeprecated(非推奨)の公式発表こそありませんが開発が止まっています。
ですので、Go言語でホットリロードを実現する場合はAirの利用がオススメです。

今回はAirをインストールし、Go言語のホットリロードを実現する手順について紹介します。

今回利用するサンプルコード

今回は以下のHTTPサーバの実装をサンプルとして利用します。

main.go

package main

import (
    "log"
    "net/http"
)

func rootHander(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(200)
    w.Header().Set("Content-Type", "text/html; charset=utf8")
    w.Write([]byte("こんにちは"))
}

func main() {
    http.HandleFunc("/", rootHander)
    log.Fatal(http.ListenAndServe(":3000", nil))
}

Airの設定方法

Airの設定手順について紹介します。

インストール

go installでバイナリファイルをインストールします。

$ go install github.com/cosmtrek/air@latest

### airが存在していればOK
$ which air

~/go/bin/air

設定のカスタマイズ

Airを利用してGoファイルを実行すると、デフォルトでtmpディレクトリにmainという名前のバイナリファイルが作成されますが、設定ファイルを用意することでカスタマイズできます。

Airの設定を変更したい場合は以下の手順で設定ファイルを用意します。デフォルトの設定で問題ない場合は設定ファイルの作成は不要です。

### 作業ディレクトリへ移動
cd /path/to/working_directory

### Airの初期化
$ air init

  __    _   ___
 / /\  | | | |_)
/_/--\ |_| |_| \_ , built with Go

.air.toml file created to the current directory with the default settings

$ ls -a .air.toml
→ .air.tomlが存在していればOK

.air.toml

### 設定ファイルをカスタマイズする
vim .air.toml

.air.tomlの設定例はair/air_example.tomlに公開されています。

ホットリロードの動作確認

go runの代わりにairで起動をするとホットリロードが可能になります。

airコマンドは.air.tomlがカレントディレクトリに存在していれば設定を読み込みます。存在しなければデフォルトの設定でGoファイルを起動します。
設定ファイルを指定する場合は-cオプションを利用して、air -c /path/to/.air.tomlという形でコマンドを実行します。

$ cd /path/to/working_directory

### airで起動するにはgo.modが必要なので、なければ作成する
$ go mod init example

$ ls
go.mod  main.go

$ air

  __    _   ___
 / /\  | | | |_)
/_/--\ |_| |_| \_ , built with Go

watching .
!exclude tmp
building...
running...


curlを実行すると以下のような結果になります。

$ curl http://localhost:3000

こんにちは

ホットリロードが機能しているか確認するため、main.goを以下のように修正してみます。

main.go

  w.Header().Set("Content-Type", "text/html; charset=utf8")
- w.Write([]byte("こんちには"))
+ w.Write([]byte("Hello"))
}

main.goを保存するとairのアプリケーションログにファイル変更とビルドのログが表示されます。

sample.go has changed
building...
running...

再度curlをすると変更内容が反映されていることがわかります。

$ curl http://localhost:3000

Hello

参考: AirのDockerイメージを利用する場合

AirはDockerイメージを公開しています。AirのDockerイメージを利用することでローカルにAirをインストールしなくてもホットリロードを実現できます。

Dockerイメージを利用してAirでGoファイルを起動する手順は以下の通りです。

### 作業ディレクトリへ移動
$ cd /path/to/working_directory

### main.goとgo.modがあることを確認
$ ls
go.mod  main.go

### cosmtrek/air イメージを利用してコンテナを起動
$ docker run -it --rm --name air-container -w "/app" -v $(pwd):/app -p 3000:3000 cosmtrek/air
# -it: interactive & tty
# --rm: コンテナ終了時にコンテナを削除
# --name: コンテナ名の指定。(なくてもOK)
# -w: コンテナ上でのワーキングディレクトリ
# 『-v [ローカルディレクトリ]:[コンテナディレクトリ]』: ディレクトリのバインドマウント(同期)
# -p: ポート開放(今回の場合はローカルの3000ポートでコンテナの3000ポートにアクセスできるようにする)


  __    _   ___
 / /\  | | | |_)
/_/--\ |_| |_| \_ , built with Go 1.16.3

watching .
!exclude tmp
building...
running...

プロセスを確認するとコンテナ(今回の場合はair-container)が起動していることがわかります。

$ docker ps

CONTAINER ID   IMAGE          COMMAND         CREATED          STATUS          PORTS                    NAMES
74ca6be828e8   cosmtrek/air   "/go/bin/air"   11 minutes ago   Up 11 minutes   0.0.0.0:3000->3000/tcp   air-container

コンテナ起動時のオプションの詳細はcosmtrek/air#dockerを参考にしてください。

さいごに

Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!