個人的な備忘録：簡単なGoアプリを作成しながら、ホットリロードの仕組みを紐解いてアウトプットしてみた

## はじめに
私自身、Go言語のホットリロードにはあまりなじみがありませんが、今回ハッカソンのバックエンドで採用された言語ということで、キャッチアップを進めていこうと思っています。

:::note info
***これまでバックエンドの言語としてはPythonしか使ったことがありません。正直なところ、他の言語についてはこれから学んでいく必要がある状況です。***
:::

なお、本記事は個人的な備忘録としてまとめたものです。***その点をご理解いただければ幸いです。***

## 書こうと思ったきっかけ
普段はインフラの自動化などでYAML、JSON、Pythonを使うことが多いです。

:::note warn
**しかし、1つのプログラミング言語を徹底的に習得することで、他の言語にも知識を横展開したり流用したりできると考えています。**
:::

そのため、ホットリロードの理解を深めるために、まずは動くものを作ってみようと思いました。

また、以前ローカル環境と本番環境の違いについてまとめた際にホットリロードにも触れていますので、気になる方は以下の記事を参考にしてみてください。

https://qiita.com/free-honda/items/476b73fa100d0320451b#%E3%83%9B%E3%83%83%E3%83%88%E3%83%AA%E3%83%AD%E3%83%BC%E3%83%89air%E3%81%AE%E9%81%95%E3%81%84

##  Go言語のホットリロードとは
ホットリロードとは、コードを変更した際に手動でアプリケーションを再起動することなく、変更が即時反映される仕組みです。

:::note info
**ホットリロードのメリット**
- **開発効率が大幅に向上**
  - コードを変更するたびに即時反映されるため、開発スピードが向上します。
- **サーバーを手動で再起動する手間が省ける**
  - 自動で再起動されるため、作業の中断を最小限に抑えることができます。
:::


Go言語ではデフォルトでこの機能はありませんが、外部ツールを使用して簡単に実現できます。

### Go言語でホットリロードを実現する方法

主に以下の外部ツールが使用されます。

- **Air**
  - 人気のあるホットリロードツール。
  - 設定が簡単で、Goプロジェクトで広く使われています。
- **Reflex**
  - ファイル変更を監視してコマンドを再実行できる軽量ツール。

ここでは、**Air** を使用したホットリロードの設定と簡単な実装例を紹介します。

## 事前準備：Airのセットアップ手順
- **Airコマンドのインストール**
  - `air` コマンドは `$GOPATH/bin` にインストールされます。

```bash
go install github.com/air-verse/air@latest
```

**実際のコマンド結果**

```bash
➜  Desktop git:(main) ✗ go install github.com/air-verse/air@latest
go: downloading github.com/air-verse/air v1.61.7
go: downloading dario.cat/mergo v1.0.1
go: downloading github.com/fatih/color v1.17.0
go: downloading github.com/gohugoio/hugo v0.134.3
go: downloading github.com/pelletier/go-toml v1.9.5
go: downloading github.com/fsnotify/fsnotify v1.7.0
go: downloading github.com/mattn/go-isatty v0.0.20
go: downloading golang.org/x/sys v0.25.0
go: downloading github.com/bep/golibsass v1.2.0
go: downloading golang.org/x/text v0.18.0
go: downloading github.com/bep/godartsass/v2 v2.1.0
go: downloading github.com/pelletier/go-toml/v2 v2.2.3
go: downloading github.com/bep/godartsass v1.2.0
go: downloading github.com/spf13/afero v1.11.0
go: downloading github.com/tdewolff/parse/v2 v2.7.15
go: downloading github.com/spf13/cast v1.7.0
go: downloading github.com/gobwas/glob v0.2.3
go: downloading github.com/cli/safeexec v1.0.1
go: downloading google.golang.org/protobuf v1.34.2
```

- **PATHを設定**
  - インストール後、`$GOPATH/bin` を PATH に追加します（まだ設定していない場合）。

```bash
export PATH=$PATH:$(go env GOPATH)/bin
```

**設定が完了したら以下で確認します：**

```bash
air -v
```

**実際のコマンド結果**

```bash
➜  Desktop git:(main) ✗ air -v

  __    _   ___  
 / /\  | | | |_) 
/_/--\ |_| |_| \_ v1.61.7, built with Go go1.23.4

```

バージョン情報が表示されればインストール完了です。

- **Airの設定ファイルを作成**
  - プロジェクトのルートディレクトリで以下のコマンドを実行して、設定ファイルを生成します：

```bash
air init
```

**実際のコマンド結果**

```bash
➜  myproject git:(main) ✗ air init

  __    _   ___  
 / /\  | | | |_) 
/_/--\ |_| |_| \_ v1.61.7, built with Go go1.23.4

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

  - このコマンドを実行すると、`air.toml` という設定ファイルが生成されます。このファイルで、ホットリロードの監視設定をカスタマイズできます。

## 簡単なGoアプリをホットリロード対応で作成してみた
以下では、ホットリロード対応の簡単なGoアプリを実装する手順を紹介します。

### 1. プロジェクトのディレクトリ構成

```css
myproject/
├── main.go
```

### 2. 実際のコード

以下はアプリのコードです。このサーバーを起動すると、ブラウザや curl を使って `http://localhost:8080` にアクセスすることで、「`"Hello, Go Hot Reload!"`」のレスポンスが表示されます。

```main.go
package main

import (
	"fmt"
	"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello, Go Hot Reload!")
}

func main() {
	http.HandleFunc("/", handler)
	fmt.Println("Starting server on :8080...")
	http.ListenAndServe(":8080", nil)
}
```

「ホットリロード (コード変更のたびにサーバーを再起動せずに反映される機能)」を使うことを目的とした簡易的なコードとなっています。

### 2. Goモジュールを初期化

ターミナルで以下のコマンドを実行して、Goモジュールを初期化します。

```bash
go mod init myproject
```


### 3. Airを使った実行
ターミナルで以下のコマンドを実行します。

```bash
air
```

- **サーバーの自動起動**
  - Airを使用すると、サーバーが自動的に起動します。
  - `main.go` を変更すると、Airが変更を検知し、変更内容が即時反映されます。

## ブラウザでアクセスしてみた

サーバーが起動したら、ブラウザで `http://localhost:8080` にアクセスします。

![Screenshot 2025-01-27 at 6.32.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/a18ffb17-e0c5-7205-4733-a8ebefb7cd89.png)

- **コードの変更例**
  - `main.go` の `fmt.Fprintln(w, "Hello, Go Hot Reload!")` を、例えば以下のように変更します。

```main.go
fmt.Fprintln(w, "Hello, Go with Hot Reload!")
```

変更を保存すると、自動的にサーバーが再起動され、変更内容が即座に反映されます。

![Screenshot 2025-01-27 at 6.35.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/f515dd90-7c99-1c4f-ae96-dc31f1711f9f.png)

これで、Go言語のホットリロードについて理解し、簡単な実装ができるようになります！

## まとめ

ここまで読んでいただき、ありがとうございました。***今回の簡単なアプリ作成を通じて、私自身も多くの学びを得ることができました。***

:::note info
**個人メモ**
***ホットリロードは開発環境での使用を想定しており、本番環境では使用しないこと***
:::

ローカル開発と本番環境の違いを正しく理解することで、アプリケーションのスムーズな切り替えが可能になると感じました。

***この記事がどなたかの技術的な参考になれば嬉しいです！***