Go言語とginで作ったHTTPサーバをHeroku上で動かしてみる

# はじめに

Goとginで作ったHTTPサーバをHeroku上で動かすまでの試行錯誤をまとめてみました。
試行錯誤の結果、ゴールへたどり着いていますので、間違いがあると思います。
いまだに深くは理解ができていません。
参考程度にどうぞ。

最低限どういった手順で進めればよいかだけを見たい場合は[まとめ](#まとめ)を見ていただければと思います。

# 環境

* OS: windows 10 Home
* Go: 1.13.6
* gin: 1.5.0
* Git: 2.25.0
* Text Editor: Atom

ローカル環境での`go run main.go`はコマンドプロンプトより行います。
ginは、`go get -u github.com/gin-gonic/gin`でローカル環境へ導入済みとします。

# ローカル環境でのテスト

『[HTML をレンダリングする](https://gin-gonic.com/ja/docs/examples/html-rendering/)』を参考にmain.goとtemplates/index.tmplを用意します。
また、フォルダ構成は以下です。

soitech-go-gin-test/
　├ templates/
　│　└ index.tmpl
　└ main.go

```html:index.tmpl
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <title>{{ .title }}</title>
    </head>
    <body>
        <h1>{{ .h1 }}</h1>
    </body>
</html>
```

```go:main.go
package main

import(
	"net/http"
	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	router.LoadHTMLGlob("templates/*")
	router.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"title": "/",
			"h1": "/",
		})
	})
	router.GET("/hoge", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"title": "hoge",
			"h1": "/hoge",
		})
	})
	router.GET("/huga", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"title": "huga",
			"h1": "/huga",
		})
	})
	router.Run()
}
```

コマンドプロンプトより`go run main.go`を実行し、ブラウザから`localhost:8080`と`localhost:8080/hoge`および`localhost:8080/huga`にアクセスし、プログラムが動いていることを確認します。

# Herokuへデプロイする

さあ！Herokuへデプロイします！
私はGitHubへファイルをコミットしたら自動的にHeroku上でデプロイされるようにしていますので、GitHubへファイルをコミットします。

```
-----> App not compatible with buildpack: https://buildpack-registry.s3.amazonaws.com/buildpacks/heroku/go.tgz
       More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure
 !     Push failed
```

さあ、エラーが出ました！
インターネットの海で色々と調べてみると、`Procfile`と`vendor/vendor.json`いうものが必要らしい...
用意してみます。

```:procfile
web: soitech-go-gin-test
```

```:vendor.json
{
	"rootPath": "github.com/soichiloYoda/soitech-go-gin-test"
}
```

コミットして、自動デプロイされると、またもやエラーです。

```
-----> Running: go install -v -tags heroku . 
main.go:5:2: cannot find package "github.com/gin-gonic/gin" in any of:
	/tmp/tmp.9lmb10Wear/.go/src/github.com/soichiloYoda/soitech-go-gin-test/vendor/github.com/gin-gonic/gin (vendor tree)
	/app/tmp/cache/go1.12.12/go/src/github.com/gin-gonic/gin (from $GOROOT)
	/tmp/tmp.9lmb10Wear/.go/src/github.com/gin-gonic/gin (from $GOPATH)
 !     Push rejected, failed to compile Go app.
 !     Push failed
```

どうやらginのimportがうまくいっていないようです。
またインターネットの海で色々調べてみると、packageの管理にはGo言語1.11より標準で使えるようになったModulesを使うようです。

こちらのページ→『[Go言語の依存モジュール管理ツール Modules の使い方](https://blog.mmmcorp.co.jp/blog/2019/10/10/go-mod/)』を参考にさせていただきました。
プロジェクトフォルダへ移動し、`vendor/`と`vendor/vendor.json`を削除して`go mod init soitech-go-gin-test`をし、`go.mod`を生成します。

```:go.mod
module soitech-go-gin-test

go 1.13
```

その後、`go build`を実行すると`go.sum`が生成され、`go.mod`内に依存モジュールの情報が記述されます。

```:go.mod
module soitech-go-gin-test

go 1.13

require github.com/gin-gonic/gin v1.5.0
```

GitHub上からも`vendor/`と`vendor/vendor.json`を削除してから`go.mod`をコミットします。
Herokuで自動デプロイされ、ようやく`Build Succeeded`となりました。
ブラウザから`soitech-go-gin-test.herokuapp.com`へ接続すると、無事HTTPサーバが動作していることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488997/174b39f3-1ce9-5c39-618c-9b7960d63de3.png)
また、`soitech-go-gin-test.herokuapp.com/hoge`と`soitech-go-gin-test.herokuapp.com/huga`へも無事接続することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488997/4fdb908e-2279-918d-7931-aa1e358e4463.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488997/4be62f05-6841-69b2-63c0-ad61ef9dceb9.png)

ちなみにですが、`Procfile`を以下のように記述してデプロイしましたが、`Procfile`はなくてもデプロイできるようです。

```:Procfile
web: soitech-go-gin-test // <- おそらく間違い
```

また、Heroku上の`Build Log`を見るに、`Procfile`は以下のように記述するのが正解なようです。

```:Build_Log
Created a Procfile with the following entries:
       		web: bin/soitech-go-gin-test
```

```:Procfile
web: bin/soitech-go-gin-test // <- おそらく正解
```

`Procfile`なしでデプロイすることができましたが、Heroku上の`Build Log`に以下のように表示されるため、Procfileは自分で作成しておいたほうがよさそうです。

```:Build_Log
If these entries look incomplete or incorrect please create a Procfile with the required entries.
       See https://devcenter.heroku.com/articles/procfile for more details about Procfiles
```

# まとめ

試行錯誤してみましたが最低限以下の手順を踏めばよさそうです、といったまとめです。

1.プロジェクトディレクトリを作成する

　`mkdir PROJECT_NAME`

2.プロジェクトディレクトリ内でmodファイルを作成する

　`go mod init PROJECT_NAME`

3.`main.go`と`templates/index.tmpl`を用意してから、一度ビルドしてmodファイルに依存モジュールの情報を記述させる。

　`go build`

4.以下のファイルをGitHubへコミットして、Heroku上にデプロイする。

* templates/index.tmpl
* go.mod
* main.go

# さいごに

とりあえず、Go言語で作成したHTTPサーバをHeroku上で動かすことができました、うれしいです。
これを元に、FormからPOSTできるものを作ってみようと思います。