Golangでホットリロードする方法

Page content

※ 過去に書いた記事を載せています。今動作するかは不明。。。。

今回、Go言語で開発を行うことがありました。

go言語は、PHPやRubyなどの言語とは異なり、ビルドをしないとソースは反映されません。

そのため、開発中は、毎回ソース変更してはコンパイルをして起動。。。。。。

Vue.JSやDjangoようにホットリロードに対応していません。 めんどくさいですよね。

でも、goには、それを解消してくれるツールがあります。

それが、Air です。

今回は、標準ライブラリでWebを起動しJsonを返す簡単なサンプルを用意しました。

環境用意

Macで作成しているのでWindowsでするときは、Bashは、適当に置き換えてください。

用意するもの、

  • エディタ
  • Dockerデスクトップ

これだけで動作します。

作成手順

1) フォルダを作成

mkdir -p air_sample && cd air_sample

2) goのファイルを作成

go.mod

module air_sample

go 1.17

main.go

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

type Response struct {
	Status      int       `json:"status"`
	Message   string    `json:"message"`
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	var buf bytes.Buffer

	response :=Response{
		Status: 0,
		Message: "こんにちわ、世界",
	}

	enc := json.NewEncoder(&buf)
	if err := enc.Encode(&response); err != nil {
		log.Fatal(err)
	}
	fmt.Println(buf.String())

	_, err := fmt.Fprint(w, buf.String())
	if err != nil {
		return
	}
}

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

3) airの設定ファイルの取得

wget https://raw.githubusercontent.com/cosmtrek/air/master/air_example.toml
mv air_example.toml .air.toml

4) Docker関連のファイル作成

Dockerfile

FROM golang:1.17-buster

# Time zone
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN apt-get update
RUN apt-get -y install libonig-dev

COPY . /go/src

# Move to project root
WORKDIR /go/src

RUN go mod download

# Install Air (For binary execution)
RUN go get -u github.com/cosmtrek/air

# Start golang app with livereload
CMD ["air", "-c", ".air.toml"]

EXPOSE 8080

docker-compose.yml

version: "3"

services:
# ---------------------------------------------------
# gin
# ---------------------------------------------------
  web:
    build:
      context: .
    container_name: web
    volumes:
      - .:/go/src
    ports:
      - 8080:8080
    tty: true
    environment:
      TZ: Asia/Tokyo

5) 起動用のバッチファイル作成

start.sh

#!/usr/bin/env bash

docker-compose stop

if [ $# != 0 ]; then
  if [ "$1" = "refresh" ]; then
    docker-compose down
  fi
fi

docker-compose up --build

実行

sh start.sh

以下のようになります。

スクリーンショット 2021-12-13 午後4.06.56.png

テスト

curl "http://localhost:8080"

これで実行できます。

実行結果

スクリーンショット 2021-12-13 午後4.07.28.png

ちゃんと動いてます。 そして、以下のように表示されてます。

{"status":0,"message":"こんにちわ、世界"}

ようやくここから本題。

今回用意したファイルは、ややこしいことしてますが、フォルダ内の「main.go」をDockerComposeで見るように工夫しています。 ですので、「main.go」を書き換えると勝手に再コンパイルがされ実行環境に反映されます。

例えば、JSONの戻り値を

	response :=Response{
		Status: 0,
		Message: "こんにちわ、世界",
	}

から

	response :=Response{
		Status: 0,
		Message: "こんにちわ、世界,Hallo",
	}

と書き込んでみます。そうすると!!

スクリーンショット 2021-12-13 午後4.08.25.png

となり再コンパイルされてます。

本当に再コンパイルされているかどうか見て見ましょう。

もう一度curlで実行。

curl "http://localhost:8080"

スクリーンショット 2021-12-13 午後4.08.40.png

戻り値が変わってますね。 本番環境では、Wireは使うとダメですが、開発環境では重宝しそうです。 Goを使用することがあれば一度やってみませんか

明日は @ya-yamamoto さん、よろしくお願いします!!