goのhot-reload

[テックタッチアドベントカレンダー](https://qiita.com/advent-calendar/2019/techtouch) ７日目担当の@analogrecordです。
前回は@ihiroky氏による「JSXとvirtual-domで遊ぶ」でした。
記事の分量・濃い内容ともに圧倒されています。流石です…

フロントエンドの記事が続いていますが、今回はバックエンドのTIPを紹介していこうと思います。

# 動機
テックタッチではサーバーサイドにgoを使用しています。
私自身テックタッチに入社するまではずっとphpとjsを書いていたため、エディタで編集してブラウザ等で即実行して挙動を確認する開発に慣れてしまっていました。
goおよびコンパイル言語を扱うのが初めてなので、少し書き直してビルドするとすぐにビルドエラーに阻まれ…どの変更によってエラーになっているのかわからなくなってしまったり、ビルドして実行できても出力結果が想定と違っている等、var_dump()してリロードすればデバッグできたphpに比べてストレスを感じていました。

[調べてみると](https://qiita.com/analogrecord/items/97073cea6380e14881be#%E5%8F%82%E8%80%83)タスクランナーのfilewatch機能を使用して、ファイル変更検知後にbuildタスクを起動してhot-reloadを実現するライブラリがありました。
いくつか試したなかでファイルの変更検知が早いrealizeがしっくり来たのでご紹介します。
go-taskも開発が活発なため魅力的でしたが、私が試した時点ではファイル変更検知までの時間がrealizeよりワンテンポ遅く感じます。

# サンプル

docker-composeでechoを使用したwebサーバのhot-reloadが試せるサンプルを用意しました。
https://github.com/mochibuta/echo-realize

リポジトリをクローン後、`docker-compose up`でechoサーバーが立ち上がります

```sh
~/Dev/go/src/github.com/mochibuta/echo-realize $ docker-compose up                                                                                                                                                          7.3s
WARNING: Native build is an experimental feature and could change at any time
Creating network "echo-realize_default" with the default driver
Creating echo-realize_server_1 ... done
Attaching to echo-realize_server_1
server_1  | [18:29:49][SERVER] : Watching 1 file/s 1 folder/s
server_1  | [18:29:49][SERVER] : Install started
server_1  | [18:29:50][SERVER] : Install completed in 1.015 s
server_1  | [18:29:50][SERVER] : Running..
server_1  | [18:29:50][SERVER] :    ____    __
server_1  | [18:29:50][SERVER] :   / __/___/ /  ___
server_1  | [18:29:50][SERVER] :  / _// __/ _ \/ _ \
server_1  | [18:29:50][SERVER] : /___/\__/_//_/\___/ v4.1.11
server_1  | [18:29:50][SERVER] : High performance, minimalist Go web framework
server_1  | [18:29:50][SERVER] : https://echo.labstack.com
server_1  | [18:29:50][SERVER] : ____________________________________O/_______
server_1  | [18:29:50][SERVER] :                                     O\
server_1  | [18:29:50][SERVER] : ⇨ http server started on [::]:1323
```

この状態でhttp://localhost:1323 へアクセスすると`Hello, World!`が出力される単純なものです。

```yaml:.realize.yaml
settings:
  legacy:
    force: false
    interval: 100ms
schema:
  - name: server
    path: .
    commands:
      install:
        status: true
        method: go build -x -o /opt/server
      run:
        status: true
        method: /opt/server
    watcher:
      extensions:
        - go
      paths:
        - /
      ignored_paths:
        - .git
        - .realize
        - vendor
```

realizeの設定は.goの拡張子のファイルの変更をウォッチし、`go run`または`go install`するようになっています。

サンプルでは`docker-compose up`時に`realize start --run`が行われるので、`main.go`に変更を加えると即座に`go run`しなおしてくれます。

ここから更にdelveデバッグ用ビルドもhot-reloadするように設定もでき、より快適に動作を確認しながらコードの改修ができるようになります。

参考でより詳しく解説されていますのでご興味のあるかたはそちらも併せて御覧ください。

---
明日は@ikazo_yによる「プロダクション readyなRedash on ECSを5分で立ち上げるためのCfn templateを作った話」です！超楽しみ


## 参考
- [mattn/echo-livereload](https://github.com/mattn/echo-livereload)
- [oxequa/realize](https://github.com/oxequa/realize)
  - [[Go] Realizeが便利なので、もう少し仲良くなってみる](
https://qiita.com/enta0701/items/9f60ad18600acab8c93d)
  - [Docker上のGoLangをリモートデバッグする](
https://qiita.com/keitakn/items/f46347f871083356149b)
- [go-task/task](https://github.com/go-task/task)
  - [go-taskでサーバーのライブリロードを実現する
](https://qiita.com/croquette0212/items/dab91c1075c1f3ac7b8d)
- [gravityblast/fresh](https://github.com/gravityblast/fresh)