GAE/Go(echo) + depでサンプルAPIサーバを作成してデプロイするまで

# GAE/Go(echo) + depでサンプルAPIサーバの作成
#### ※注意：GAE/Goに関して古い情報がかなりあるので参考にしない（特に2016年のもの）

##### 注意点
- `goapp serve, goapp deploy`は今は`dev_appserver.py, gcloud app deploy`に置き換えて考える
	- [gcloudコマンドへの移行](https://shizuoka-go.appspot.com/entry/fcd7b533-78d5-4b21-8ecb-90b8f2a0d6f7)
	- ただし、gcloudはvendoringに対応していない（後述）
	- 素直にvendoringを使いたいならgoappコマンドを使うのがよさそう
- パッケージマネジャーは公式が開発しているdepがよい（glideは使わない）

	
## 参照したドキュメント
#### GAE + Go
- [go rutime env(gcloud)](https://cloud.google.com/appengine/docs/standard/go/runtime)
- [go release note(gcloud)](https://cloud.google.com/appengine/docs/standard/go/release-notes)


## 環境構築 
### 使用した環境
- macOS High Sierra (10.13.6)
- fish shell

### GOPATHの設定
config.fishにGOPATHの設定を書く

```shell

set -x GOPATH $HOME/go
```
### goenv
goenvのインストール
goenvは複数のプロジェクトがあるが、brewでインストールできるものを入れる

```shell
> brew install goenv
```

#### config.fishに以下を追記しパスを通す

```shell
set -x GOENV_ROOT $HOME/.goenv
set -x PATH $GOENV_ROOT/shims $PATH
goenv rehash >/dev/null ^&1
```
#### コマンド

```shell
## インストールできるgoのバージョンリスト
> goenv install -l

## インストール
> goenv install 1.9.6 #gae goで対応している最新バージョン（2018/07/20）

## システム全体で使用するgoのバージョン設定
> goenv global 1.9.6
> go version #goのバージョンを確認
go version go1.9.6 darwin/amd64

## goenv helpでコマンド一覧を確認
> goenv --help
```
これでgoのバージョンを自由に設定できる

[syndbg/goenv](https://github.com/syndbg/goenv#installation)

## dep
npmのようなgoのパッケージマネジャー

[golang/dep](https://github.com/golang/dep)

### depのインストール

```shell
> brew install dep
> brew upgrade dep
```
### init
/go/src/gae-go-echo-tutorial直下で初期化すると`Gopkg.lock`と`Gopkg.toml`,`vendor/`が作成される。

すでにgoのコードがあり、なんらかのパッケージがgoのコード内でimportされている場合は、それも見て依存関係のあるパッケージまでインストール&管理してくれる

バージョンもちゃんとロックしてくれることで、チーム内での環境構築がしやすい

```shell
> dep init
```

### 新しいパッケージのインストール<br>
パッケージをgoのコード内でimportして

```shell
> dep ensure
```
でvendor以下にインストールされる

## gcloud app deployでハマったこと
`gcloud app deploy`コマンドはvendoringに対応していない（2018/07/20）

では、go getでパッケージ管理を行えばいいかというとそうでもなく、パッケージが依存しているパッケージでvondoringを利用している場合でも`gcloud app deploy`コマンドで依存しているパッケージをimportできませんとエラーが出る。<br>
例えば、echoをdepを使わずにgo getでインストールしてデプロイしようとしたが、echoが依存しているパッケージがvendoringを利用しているのでエラーが出てdeployできない（devapp_server.pyでローカルサーバーはエラーなく立ち上がる）<br>
> ERROR: (gcloud.app.deploy) Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
> /work_dir/github.com/valyala/fasttemplate/template.go:12:2: can't find import: "github.com/valyala/bytebufferpool"

なので、vendoringをしつつ、`gcloud app deploy`を行うために以下のディレクトリ構成にした。<br>
deployコマンドを打つときに$GOPATHをsrcからvendor以下にsymlinkが貼られている`gopath/`に変更することで`gcloud app deploy`でもデプロイするこができるようになる。

```shell
## GOPATHをgopathに設定する
## この辺はよしなにaliasを貼るとか、Makefileを使う
> set -x GOPATH $HOME/go/src/gae-go-echo-tutorial/gopath
```

## ディレクトリ構成
```shell
.
├── Gopkg.lock
├── Gopkg.toml
├── README.md
├── backend
│   ├── app-engine.go
│   ├── app-standalone.go
│   ├── app.go
│   ├── app.yaml
│   ├── public
│   │   └── index.html
│   └── users.go
├── gopath
│   └── src -> ../vendor
└── vendor
    ├── github.com
    │   
    └── golang.org
```

GOPATHをsymlinkを貼っているgopathにしないと出るエラー...
> ERROR: (gcloud.app.deploy) Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
> /work_dir/app-engine.go:6:2: can't find import: "github.com/labstack/echo"
> /work_dir/gae-go-echo-tutorial/vendor/github.com/valyala/fasttemplate/template.go:12:2: can't find import: "github.com/valyala/bytebufferpool"
> /work_dir/gae-go-echo-tutorial/vendor/github.com/labstack/gommon/color/color.go:9:2: can't find import: "github.com/mattn/go-colorable"
> /work_dir/gae-go-echo-tutorial/vendor/github.com/mattn/go-colorable/colorable_appengine.go:9:2: can't find import: "github.com/mattn/go-isatty"
> /work_dir/gae-go-echo-tutorial/vendor/github.com/labstack/gommon/log/log.go:15:2: can't find import: "github.com/mattn/go-isatty"
> /work_dir/gae-go-echo-tutorial/vendor/github.com/labstack/echo/middleware/basic_auth.go:8:2: can't find import: "github.com/labstack/echo"
> /work_dir/gae-go-echo-tutorial/vendor/golang.org/x/crypto/acme/autocert/autocert.go:34:2: can't find import: "golang.org/x/crypto/acme"
> /work_dir/gae-go-echo-tutorial/vendor/github.com/labstack/echo/echo.go:57:2: can't find import: "github.com/labstack/gommon/color"

これで、echoを使いつつ、gcloudコマンドでデプロイすることができた。<br>
はやくvendoringに対応してほしい…
#### 解決するために参考にした記事
- [Google App EngineのGo 1.8 Standard envでdepのvendoringなどでハマる(2017年10月現在)](http://blog.wktk.co.jp/ja/entry/2017/10/11/google-app-engine-go-vendor-directory-structure)
- [GAE/Go (+dep) で gcloud app deploy する為の構成](https://qiita.com/su_aska/items/81b983ac662691cc97b5)
- [Google App EngineでGoを動かすときに知っておくべきこと（ソースコード・ビルド編）](https://motemen.hatenablog.com/entry/2016/11/gae-go-building)