homie Tech Blog | homie株式会社エンジニアブログ

homie株式会社エンジニアによる不動産テック領域のプロダクト開発を支える技術や取り組みについて発信しています。

【Golang/Go言語】Goのホットリロードライブラリをrealizeからairに移行しました

f:id:pointenko:20210105150323p:plainはじめまして

homie株式会社のエンジニア池見です。

先日、Goのホットリロードライブラリをrealizeからairに移行したので、移行した理由やairについて調べたことを記載します。


realizeからairに移行した理由

今までの開発において、ホットリロードライブラリにはrealizeを使っていました。 しかし、メンテナンスが止まっており、issues/253のようなエラーでハマることがありました。 他のライブラリを調べたところ、airというライブラリが現在も開発されており、star数も多かったので、こちらを利用することにしました。 github.com

docker imageも用意されています。

airのメリット

airGithubリポジトリをざっと見て、以下のメリットがあると思いました。

  • 設定ファイルの記述が簡単
  • build/binaryコマンドをカスタマイズできる
  • air起動後に作成したディレクトリも監視できる
  • ログが色付けされていて見やすい

airの導入方法

以下のようなサンプルを用意して説明します。

$ tree -a         
.
├── .air.toml
└── main.go

0 directories, 2 files

main.goは以下の通りです。

package main

import (
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("HelloWorld\n"))
    })

    http.ListenAndServe(":8080", nil)
}

1. airのインストール

$ go get -u github.com/cosmtrek/air

2. airの設定ファイル(.air.toml)作成

$ touch .air.toml

基本的に公式のサンプルファイルair_example.tomlを参考に、自身の環境に合わせて設定します。

今回はair_example.tomlをほぼそのまま流用します。

# Config file for [Air](https://github.com/cosmtrek/air) in TOML format

# Working directory
# . or absolute path, please note that the directories following must be under root.
root = "."
tmp_dir = "tmp"

[build]
# Just plain old shell command. You could use `make` as well.
cmd = "go build -o ./tmp/main ."
# Binary file yields from `cmd`.
bin = "tmp/main"
# Customize binary.
full_bin = "./tmp/main"
# Watch these filename extensions.
include_ext = []
# Ignore these filename extensions or directories.
exclude_dir = ["tmp"]
# Watch these directories if you specified.
include_dir = []
# Exclude files.
exclude_file = []
# Exclude unchanged files.
exclude_unchanged = true
# This log file places in your tmp_dir.
log = "air.log"
# It's not necessary to trigger build each time file changes if it's too frequent.
delay = 1000 # ms
# Stop running old binary when build errors occur.
stop_on_error = true
# Send Interrupt signal before killing process (windows does not support this feature)
send_interrupt = false
# Delay after sending Interrupt signal
kill_delay = 500 # ms

[log]
# Show log time
time = false

[color]
# Customize each part's color. If no color found, use the raw app log.
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
# Delete tmp directory on exit
clean_on_exit = true

設定項目は難しくなく直感で分かると思います。

重要な項目を簡単に説明します。

1. cmd

アプリケーションをコンパイルするコマンドを記述します。

[build]
//...
cmd = "go build -o ./tmp/main ."
//...

makeコマンドも使えます。

cmd = "make build"

2. bin

cmdでbuildしたbinaryのpathを指定します。

[build]
//...
bin = "tmp/main"
//...

3. full_bin

アプリケーションの起動方法を設定できます。 例えば以下のように起動時に環境変数や引数を渡すことができます。

[build]
//...
full_bin = "APP_ENV=dev tmp/main foo"
//...

4. tmp_dir

airのログファイルが出力されるパスです。ビルド生成物置き場としても使用できます。

air起動時に作成され、終了時に削除されます。

[build]
//...
tmp_dir = "tmp"
//...

5. exclude_dir

exclude_dirは、監視対象外のディレクトリを指定します。

[build]
//...
exclude_dir = ["tmp"]
//...

6. delay

delayコンパイルの実行タイミングを遅らせることができます。 ファイルを頻繁に変更する場合に、コンパイル回数を減らすのに役立ちます。

[build]
//...
delay = 1000 # ms
//...

アプリケーションの起動

airコマンドで起動できます。

$ air

  __    _   ___  
 / /\  | | | |_) 
/_/--\ |_| |_| \_  // live reload for Go apps, with Go 

mkdir /Users/ryoikemi/work/air_sample/tmp
watching .
!exclude tmp
building...
running...

リクエストを飛ばすとレスポンスが返ってきます。

$ curl localhost:8080
HelloWorld

main.goHelloWorldGoodbyeWorldに変更してみると、再コンパイルされます。

main.go has changed
building...
running...

レスポンスも変わっています。

$ curl localhost:8080
GoodbyeWorld

まとめ

  • realizeはメンテナンスされてなく、開発中にバグを踏んで生産性低下の原因になる
  • realizeの代替手段としてairが良さそう