Heroku への Go 言語製アプリケーションのデプロイと依存パッケージ管理方法の比較

# はじめに
* Go 言語製のアプリケーションを Heroku で動かす場合、`heroku create` などの Heroku アプリケーション作成時になどに公式のビルドパック (https://github.com/heroku/heroku-buildpack-go) を指定する必要があります。
* このビルドパックでは依存パッケージ管理方法として `govendor`, `Godep`, `GB`, `glide` を利用することができるのでそれぞれの場合の簡単な手順の確認と比較をしてみました。
  * `glide` は最近対応したようなので公式にドキュメントが無いですが、ビルドパックの README から確認できます

# アプリケーションの準備
* `github.com/urfave/negroni` の README にあるものをほぼそのまま使って、依存パッケージを持つ簡単なウェブアプリケーションを用意しました。
* Heroku に対応するために公開ポート番号を `PORT` を環境変数から取得するように変更してあります。
  * Heroku へデプロイするための対応は先述のビルドパックと、このポート番号の参照と、Procfile の準備、後述の依存パッケージ管理の 4 点が必要最低限のものになります。

## main.go の作成
* 以下のファイルを `main.go` として作成します

```go
package main

import (
        "fmt"
        "github.com/urfave/negroni"
        "net/http"
        "os"
)

func main() {
        mux := http.NewServeMux()
        mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
                fmt.Fprintf(w, "Welcome to the home page!")
        })

        n := negroni.Classic() // Includes some default middlewares
        n.UseHandler(mux)

        port := os.Getenv("PORT")
        if port == "" {
                port = "3000"
        }
        http.ListenAndServe(":"+port, n)
}
```

## Procfile の作成
* 以下のコマンドを実行して Heroku アプリの起動時に参照される Procfile を作成します

```sh
echo "web: $(basename `pwd`)" > Procfile
```

# 各依存パッケージ管理方法ごとの簡単な手順

## govendor
* 公式ドキュメントは https://devcenter.heroku.com/articles/go-dependencies-via-govendor

```sh
# govendor のインストール
go get -u github.com/kardianos/govendor
# 初期化
govendor init
# 設定ファイルの更新と依存パッケージの vendor へのダウンロード
govendor fetch +out
# デプロイ対象を git 管理下に
git add Procfile main.go vendor/vendor.json # vendor.json を git add しさえすれば依存パッケージのソースは add する必要ない
git commit
# Heroku アプリの作成とデプロイ
heroku create -b https://github.com/heroku/heroku-buildpack-go
git push heroku master
```

## Godep
* 公式ドキュメントは https://devcenter.heroku.com/articles/go-dependencies-via-godep

```sh
# Godep のインストール
go get github.com/tools/godep
# 依存パッケージのインストール
go get github.com/urfave/negroni
# 依存パッケージを vendor にコピー
godep save
# デプロイ対象を git 管理下に
git add Godeps Procfile main.go vendor
git commit
# Heroku アプリの作成とデプロイ
heroku create -b https://github.com/heroku/heroku-buildpack-go
git push heroku master
```

## GB
* 公式ドキュメントは https://devcenter.heroku.com/articles/go-dependencies-via-gb
  * ですが…なんかうまくできませんでした
  * GB の README によると `gb is an alternative build tool for the Go programming language.` ということなので依存パッケージ管理だけの用途で使うのは役不足っぽいので除外します

## glide
* 公式ドキュメントは https://devcenter.heroku.com/articles/go-dependencies-via-glide ですが準備中のようです

```sh
# glide のインストール
curl https://glide.sh/get | sh
# 初期化
glide init
# ソースから依存関係を読み取って vendor にダウンロード
glide install
# デプロイ対象を git 管理下に
git add Procfile glide.lock glide.yaml main.go
git commit
# Heroku アプリの作成とデプロイ
heroku create -b https://github.com/heroku/heroku-buildpack-go
git push heroku master
```

# 各依存パッケージ管理方法ごとの比較
* 試してみた主観ですがメリットとデメリットをあげてみます。

## govendor

### メリット
* vendor 管理に特化しているのでシンプルで扱いやすい
* vendor 以下のソースを git で管理する必要が無い
* Heroku の公式ドキュメントで一番最初の紹介されている

### デメリット
* 特に無い。名前が長いくらい。

## Godep

### メリット
* 歴史があり安定している？
* `godep save` で設定ファイルを自動生成できる

### デメリット
* vendor 以下のソースを git で管理する必要がある
* 一度 `go get` しておかないとパッケージを取ってこれない

## glide

### メリット
* vendor 以下のソースを git で管理する必要が無い
* `glide init` でソースから依存パッケージを確認して設定ファイルを生成してくれる
* `glide install` でリモートから直接 vendor に依存パッケージのソースをダウンロードしてくれる
  * なので事前に `go get` しておく必要がなく $GOPATH に不要なファイルをおく必要もなくなる

### デメリット
* `*_test.go` もダウンロードしてくるのでちょっとディスク使用量が大きくなる
  * Godep, govendor は `*_test.go` は無視する

# おわりに
* glide に現状不満は無いですが、この記事をきっかけに govendor を知ることができシンプルなところが気に入ったのでもうちょっと govendor を使ってみようと思いました。

# 追記
* `govendor fetch +out` で設定ファイルの自動作成とリモートから vendor へのダウンロードができるのがわかったので修正