GAE(GCP)+GO+glide(dep)の正しい構成

---

**2019/04/15追記：go111になり、さらにgo.modへの移行が進められているようなので状況が以下の内容からかなり変わりました。以下はあまり推薦されないやり方になりましたのでご注意ください。**

---

2018/01/15追記：現在Glideからdepに移行するようにGlideのgithubで通知されています、これから始める方はdepで構成してみてください。

---

ただディレクトリ構成はGlideの時と一緒で問題なく動くようなので、Glideの部分をdepに読み替えてもらって記事を読んでいただければ参考になると思います。

https://github.com/Masterminds/glide

> The Go community now has the dep project to manage dependencies. Please consider trying to migrate from Glide to dep. If there is an issue preventing you from migrating please file an issue with dep so the problem can be corrected. Glide will continue to be supported for some time but is considered to be in a state of support rather than active feature development.

# はじめに

GAE(GCP)+GO+glide(dep)という構成についてあまり情報がなかったのでまとめる。
ここでは構成の説明しかしないので「GAE(GCP)」「GO」「glide(dep)」についてある程度知識があるものとして話を進める。

結論から言うとGO言語の基本をちゃんと知っててglide(dep)のREADMEを読んでいれば困らない内容。
自分のようなGO初心者向け。

前提知識も色々書くので、結論だけ知りたい場合は全部すっ飛ばして最後を見てください。

# GOPATHの基本

GO初心者が見落としがちな部分としてGOPATH配下の構成がある。
他の言語から入ってくると非常に分かりづらいが、GOPATH配下の構成はある程度決まっていて、その構成を前提にGO関連の色々は動いている。

分かりづらいと言っても、以下の本家ページなどを読めばちゃんと書いてある。
https://golang.org/doc/code.html#Workspaces

### 構成イメージ
```
{GOPATH}
 ├ src
 │  ├ myGoLogic (自分のGOプログラム)
 │  ├ github.com/hoge (go get　とかで取り込んだ外部ライブラリ)
 │  └ golang.org/hoge (go get　とかで取り込んだ外部ライブラリ)
 ├ bin (Goのコマンド実行形式ファイルが入る)
 └ pkg (コンパイルされたパッケージが入る)
```

**大事なのは src 配下にディレクトリを作って自分のプログラムを書くということ。**
src/{プロジェクト名}　のような感じ。

他の言語から入った人間だと、外部ライブラリと自分のコードが同列の場所にあるのに戸惑うと思うがGO言語ではこういうものらしい。

# Vendoringの基本

Vendoringの仕組みがGOに入るまでは、**GOPATHの基本**で説明したように自分のプロジェクトと同列に外部ライブラリを管理していた。ただ、プロジェクト毎に外部ライブラリを管理したい時に困ってしまうわけで（いわゆるグローバルを汚染したくないというやつ）、それを回避するためにGOPATHを毎度書き換えたり、別途ツールを使っていたりした。

それをGO言語自体が解消するために入れられた仕組みが Vendoring。
具体的には、**各プロジェクトディレクトリ配下かその親ディレクトリに vendor という名前のディレクトリを作り、その中に依存パッケージを配置するとプロジェクト配下にある自分のGOプログラムからvendor内のパッケージが参照できるようになる。**

### 構成のイメージ
```
{GOPATH}
 ├ src
 │  ├ myGoLogic (プロジェクト１)
 │  │　├ main.go (自分のGOプログラム)
 │  │　└ vendor
 │  │　　  ├ github.com/hoge (go get　とかで取り込んだ外部ライブラリ)
 │  │　　  └ golang.org/hoge (go get　とかで取り込んだ外部ライブラリ)
 │  └ myGoLogic2 (プロジェクト２)
 │　    ├ main.go (自分のGOプログラム)
 │　    └ vendor
 │　　      ├ github.com/hoge (go get　とかで取り込んだ外部ライブラリ)
 │　　      └ golang.org/hoge (go get　とかで取り込んだ外部ライブラリ)
 ├ bin
 └ pkg
```

上記の構成にすると自分で書いたGOプログラム内で以下のように読み込めるようになる。

```
import　"github.com/labstack/echo"
```

ちなみに、glide(dep)がやってくれるのはvendorの中に入るライブラリの管理。

# 結論

まずポイントをおさらい
 
- {GOPATH}/src/{自分のプロジェクト}/ に自分のコードを配置する
- {GOPATH}/src/{自分のプロジェクト}/vendor に外部ライブラリを置く

### 上記の基本を理解した上での最終的な構成。
GAEは１つのプロジェクトに複数のサービスを持てるのでそれを考慮した構成にした。

```
{GOPATH}
　└ src
　　├ myGaeService1 (サービス１)
　　│　├ app.go (app.yamlが最初に呼び出すコード)
　　│　├ app.yaml
　　│　├ glide.yaml
　　│　├ myGaeService1Logic (app.goから呼び出されるコード)
　　│　└ vendor (glide(dep)でいれたやつ)
　　└ myGaeService2 (サービス２)
　　　　├ app.go (app.yamlが最初に呼び出すコード)
　　　　├ app.yaml
　　　　├ glide.yaml
　　　　├ myGaeService2Logic (app.goから呼び出されるコード)
　　　　└ vendor (glide(dep)でいれたやつ)
```

この構成であれば、importする時もそれぞれのサービス配下にあるvendorを見に行ってくれる。
デプロイ時もGOPATHの中身を全部含めてしまうこともなく、ちゃんと各サービスのファイルのみデプロイされる。

> GAEのサービス一覧右端にある「診断」から「デバッグ」を選ぶとデプロイされたファイルが確認できる。

> またネットに転がっている情報だと、app.yamlに vendor の中身をビルドしないように nobuild_files を設定しないとエラーが出ると書いてあるところもあるが、この構成の場合 nobuild_filesを設定しなくてもエラーは出ない。

サービスをローカルで動かしたい時は普通にgoapp serveをすれば良い。
ついでにデプロイコマンドも記載。

##### サービス１の起動とデプロイ

```
cd {GOPATH}/src
goapp serve ./myGaeService1/app.yaml
goapp deploy ./myGaeService1/app.yaml (デプロイ時)
```
##### サービス２の起動とデプロイ

```
cd {GOPATH}/src
goapp serve ./myGaeService2/app.yaml
goapp deploy ./myGaeService2/app.yaml (デプロイ時)
```

##### サービスを複数起動したい場合と複数同時デプロイ

```
cd {GOPATH}/src
goapp serve ./myGaeService2/app.yaml ./myGaeService1/app.yaml
goapp deploy ./myGaeService2/app.yaml ./myGaeService1/app.yaml (２つ同時にデプロイもできる)
```

起動が成功するとローカルのGAE管理ページでサービスが複数立ち上がっているのが確認できる。
![スクリーンショット 2017-05-12 7.56.22.png](https://qiita-image-store.s3.amazonaws.com/0/35536/30f72b80-a345-c4b8-c28a-a4edfdef248b.png)



> 実はこの記事を書くきっかけになったのが、ローカルでのサービス複数起動。
元々の構成だとサービス同時起動がどうしてもできず、１日ぐらい頭を悩ませた。
結局 GOPATHとVendoringについて理解してないだけだった。

以上、自分はこの構成を得るまでに１日かかってしまったので、同じように悩む人の参考になればと思う。