💜

Airで始めるGo開発

2023/12/18に公開

RetailAI Adventurers Advent Calendar 2023の18日目の記事になります。

今回、僕の担当しているプロジェクトで、.air.tomlという見慣れないファイルを見つけたので、それについて調べてみました。

.air.tomlとは、Go言語のホットリロードツールであるAirの設定ファイルです。

https://github.com/cosmtrek/air

ホットリロードとは、ソースコードを更新するたびにソースをビルドし直して実行するという手間を省くため、ソースコードを更新し、保存したら自動でビルドと実行を行うということです。

プロジェクトのルートディレクトリでairを実行し、放っておくだけでコードに集中できるというわけです。

https://github.com/urakawa-jinsei/air-tutorial

Installation

  • Airをインストールします
$ go install github.com/cosmtrek/air@latest
  • パスに追加します
$ export PATH=$PATH:$(go env GOPATH)/bin
  • .air.tomlファイルをデフォルト設定で作成します
$ air init
.air.toml
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
  args_bin = []
  bin = "./tmp/main"
  cmd = "go build -o ./tmp/main ."
  delay = 1000
  exclude_dir = ["assets", "tmp", "vendor", "testdata"]
  exclude_file = []
  exclude_regex = ["_test.go"]
  exclude_unchanged = false
  follow_symlink = false
  full_bin = ""
  include_dir = []
  include_ext = ["go", "tpl", "tmpl", "html"]
  include_file = []
  kill_delay = "0s"
  log = "build-errors.log"
  poll = false
  poll_interval = 0
  post_cmd = []
  pre_cmd = []
  rerun = false
  rerun_delay = 500
  send_interrupt = false
  stop_on_error = false

[color]
  app = ""
  build = "yellow"
  main = "magenta"
  runner = "green"
  watcher = "cyan"

[log]
  main_only = false
  time = false

[misc]
  clean_on_exit = false

[screen]
  clear_on_rebuild = false
  keep_scroll = true
.air.tomlの詳細

.air.tomlファイルの各設定値の詳細は以下の通りです:

  • root:プロジェクトのルートディレクトリを指定します。

  • testdata_dir:テストデータが格納されているディレクトリを指定します。

  • tmp_dir:一時ファイルが格納されるディレクトリを指定します。

  • [build]:ビルドに関する設定を行います。

    • args_bin:ビルドコマンドに渡す引数を指定します。
    • bin:ビルド後の実行ファイルの出力先を指定します。
    • cmd:ビルドコマンドを指定します。
    • delay:ファイル変更検出後、ビルドを開始するまでの遅延時間(ミリ秒)を指定します。
    • exclude_dir:ビルドから除外するディレクトリを指定します。
    • exclude_file:ビルドから除外するファイルを指定します。
    • exclude_regex:ビルドから除外する正規表現を指定します。
    • include_dir:ビルドに含めるディレクトリを指定します。
    • include_ext:ビルドに含める拡張子を指定します。
    • include_file:ビルドに含めるファイルを指定します。
    • kill_delay:プロセス終了後、新しいプロセスを開始するまでの遅延時間を指定します。
    • log:ビルドエラーのログを出力するファイルを指定します。
  • [color]:ログの色設定を行います。

    • app:アプリケーションのログ色を指定します。
    • build:ビルドのログ色を指定します。
    • main:メインのログ色を指定します。
    • runner:ランナーのログ色を指定します。
    • watcher:ウォッチャーのログ色を指定します。
  • [log]:ログに関する設定を行います。

    • main_only:メインのログのみを出力するかどうかを指定します。
    • time:ログに時間を表示するかどうかを指定します。
  • [misc]:その他の設定を行います。

    • clean_on_exit:終了時にクリーンアップを行うかどうかを指定します。
  • [screen]:スクリーンに関する設定を行います。

    • clear_on_rebuild:再ビルド時にスクリーンをクリアするかどうかを指定します。
    • keep_scroll:スクロールを保持するかどうかを指定します。

Preparation

main.go
package main

import "fmt"

func main() {
	fmt.Println(Hello())
}

func Hello() string {
	return "Hello"
}

Dockerfile
FROM golang:1.21-alpine

WORKDIR /app

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

COPY go.mod go.sum ./
RUN go mod download

CMD ["air", "-c", ".air.toml"]
docker-compose.yaml
version: "3.8"
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    volumes:
      - ./:/app

Execution

それでは、実際に変化を見ていきましょう

  • コンテナを起動します
$ docker-compose up
  • ファイルを編集します
main.go
package main

import "fmt"

func main() {
	fmt.Println(Hello())
}

func Hello() string {
-	return "Hello"
+	return "Hello, World!"
}

  • 自動でビルドされ、実行されます
    Untitled (4).png

Testing

ソースコードを変更すると、自動でテストが走るようにしたいと思います。

  • テストファイルを作成します。
main_test.go
package main

import (
	"testing"
)

func TestHello(t *testing.T) {
	result := Hello()
	expected := "Hello, World!"

	if result != expected {
		t.Errorf("Expected %s, but got %s", expected, result)
	}
}

  • .air.tomlにテストのコマンドを追加します。
.air.toml
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
  args_bin = []
  bin = "./tmp/main"
- cmd = "go build -o ./tmp/main ."
+ cmd = "go test ./... && go build -o ./tmp/main ."
  delay = 1000
  exclude_dir = ["assets", "tmp", "vendor", "testdata"]
  exclude_file = []
  exclude_regex = ["_test.go"]
  exclude_unchanged = false
  follow_symlink = false
  full_bin = ""
  include_dir = []
  include_ext = ["go", "tpl", "tmpl", "html"]
  include_file = []
  kill_delay = "0s"
  log = "build-errors.log"
  poll = false
  poll_interval = 0
  post_cmd = []
  pre_cmd = []
  rerun = false
  rerun_delay = 500
  send_interrupt = false
  stop_on_error = false
  [以下略]
  • 実行します。

Untitled (5).png

自動でテストが走りました。

Finally

これのおかげで、開発がだいぶ楽になった気がします。
これからの開発でも積極的に使用していきたいと思いました。
簡単ですが、以上になります。ご覧いただきありがとうございました。

Discussion