Go言語で開発したWebアプリをGCP(GAE)へデプロイする

# はじめに
Go言語で開発したWebアプリ(HTTPによって通信を行うプログラム)を
GCPに作成したGAEへデプロイするまでの手順を記載します。

開発したWebアプリは
Google Cloud SDKのローカルサーバーで動作確認を行った後、
GAEへデプロイして動作確認を行います。

# GAE(Google APP Engine)とは
[おさらい](https://qiita.com/melty_go/items/78e70fd6b4206d6da681)しておきますと、GAE(Google APP Engine)とは、
開発したウェブアプリケーション(PHP・Python・Java・Go言語)を
Googleのインフラストラクチャー上で実行、バージョン管理するためのGCPサービスです。

# 前提
・[git](https://gitforwindows.org/)がインストール済みであること。go getで使用します。
・[Go用Cloud SDK(248.0.0)](https://cloud.google.com/appengine/docs/standard/go/download)がインストール済みであること
　　<font color="blue">⇒インストール時にAll Usersを選択し、インストール先は「C:\go_appengine_sdk」を指定</font>
・[GCP](https://console.cloud.google.com/?hl=ja)にて `ナビゲーションメニュー ＞ App Engine` が作成済みであること。無料トライアルでもOK
　　<font color="red">※GAEへデプロイせず、ローカルサーバーで実行確認をするだけなら不要</font>

# Go言語で簡単なWebアプリを開発
![GCP_GAE_Go.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/b3c8c4c4-ad3a-75bc-85ec-629995c33fd5.jpeg)
JSONでレスポンスを返すシンプルなWebアプリと、
Webアプリを構成するためのyamlファイルを開発してみます。

## goファイルを準備
以下のgoファイルをローカルに準備します。
処理の詳細はコメントをご覧ください。

```helloHttpServer.go
// このソースファイルは「main」パッケージに属すことを指定しています。
// また、Go言語のソースファイルは必ず「package」文で始まります。
package main

// 一つの import ステートメントで複数のパッケージをインポートしています。
import (
	// HTTPを扱うパッケージです。
	// HTTPクライアントとHTTPサーバーを実装するために必要な機能が提供されています。
	"net/http"

	// JSONを扱うパッケージです。
	// JSONのエンコードとデコードをを実装するために必要な機能が提供されています。
	"encoding/json"

	// GAEのAPIを扱うコンテキストのパッケージです。
	// 下記はGo1.6までのコンテキストでして、最近のGAEに使用されております。
	// ※Go1.7からのGo標準のコンテキストは「context.Context」ですが、現在GAEはGo1.6なので使えないです。
	"google.golang.org/appengine"
)

// レスポンスパラメータ用の構造体です。
//   ・JSON：XMLなどと同様のテキストベースのデータフォーマットです。
// typeで構造体の型(Response)を宣言しています。構造体型以外の型にも名前をつけることができます。
// structで構造体(名前と型を持つフィールドの集まり)を宣言しています。
type Response struct {
	// フィールド名 型     タグと呼ばれるメタデータ。「Status」ではなく「status」でjsonを整えてくれる。
	Status          string `json:"status"`
	Message         string `json:"message"`
}

// main関数は実行可能プログラムのエントリポイント
func main() {
	// 第一引数にURL、第二引数にハンドラを渡し、DefaultServeMuxに登録する。
	// つまり、「/」というURLがリクエストされた際に、handlerが起動する。
	//   ・URL            ：HTTPリクエストのパターン
	//   ・ハンドラ        ：リクエストに対する応答
	//   ・DefaultServeMux：パターンにマッチしたリクエストに対して、そのパターンを持つhandlerを返却
	http.HandleFunc("/", handle)

	// GAEでリクエストを受信するためのHTTPサーバーを起動します。
	appengine.Main()
}

// JSONでレスポンスを返す関数
func handle(w http.ResponseWriter, r *http.Request) {

	// NewEncoder関数:「w」に書き込みを行う、新しいEncoderを返却
	// Encode関数    :「Response」のJSONエンコーディングを接続「w」に書込
	// Response構造体:各フィールドへ値を代入
	json.NewEncoder(w).Encode(Response{Status: "ok", Message: "Hello world!"})
}

```

## yamlファイルを準備
以下のyamlファイルをローカルに準備します。
配置先のディレクトリはgoファイル「helloHttpServer.go」と同じ場所にしてください。

```yaml:app.yaml
# YAMLのルールに従って記述された設定ファイルです。
# App EngineのGoアプリを構成するには、app.yamlファイルを使用します。(固有のファイル名を指定可能)

# Goランタイム環境を選択します。
runtime: go

# 使用するGoランタイム環境のバージョンです。
# go1はGoの最新リリース(現時点でGo1.9)のエイリアスです。
api_version: go1

# 必須要素。URL パターンと処理方法の説明のリストを定義します。
handlers:

# handlersで必要な要素。正規表現を使用したURLパターンを定義します。
# 先端の「- 」は、ハッシュのリストです。
# リストとするためにはハイフンを使い、さらにインデントを揃えてハッシュのキーを列挙します
- url: /

# アプリケーションのルート ディレクトリを起点として、このスクリプトへのパスを指定します。
# Goアプリの場合、scriptには常に_go_appの値を含める必要があります。
  script: _go_app

```

# ローカルサーバーで動作確認
GAEへデプロイする前に、
次の手順でローカルサーバーで動作確認を行ってみます。

**■手順**
　1.Windowsのコマンドプロンプトを起動

　2.GAEのAPIを扱うパッケージを取得

```console:コマンドプロンプト
go get google.golang.org/appengine
```

　3.「goファイルとyamlファイルがあるディレクトリ」配下へ移動

```console:コマンドプロンプト
cd [goファイルとyamlファイルがあるディレクトリ]
```

　4.ローカルサーバーを起動

```console:コマンドプロンプト
C:\go_appengine_sdk\google-cloud-sdk\platform\bundledpython\python.exe C:\go_appengine_sdk\google-cloud-sdk\bin\dev_appserver.py app.yaml
```
　　Google Cloud SDKのpython.exeでローカルサーバー(dev_appserver.py)を起動します。
　　引数として与えるapp.yamlは、項目「[yamlファイルを準備](https://qiita.com/melty_go/items/074af694aa8a1c8ec798#yaml%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E6%BA%96%E5%82%99)」で作成したファイルです。

　　ソースコード(helloHttpServer.go か app.yaml)を書き換えると、自動的にリビルドされます。

　5.ブラウザからローカルサーバーへアクセス
　　http://localhost:8080/

　　**【アクセス結果】**
![hellogae.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/3eadcd47-5f25-faeb-a5f1-594e2fc16891.jpeg)

# GAEへデプロイ
次の手順でGAEへデプロイして公開してみます。

**■手順**
　1.Windowsのコマンドプロンプトを起動

　2.「goファイルとyamlファイルがあるディレクトリ」配下へ移動

```console:コマンドプロンプト
cd [goファイルとyamlファイルがあるディレクトリ]
```

　3.デプロイコマンドを実行

```console:コマンドプロンプト
gcloud app deploy --project [GCPのプロジェクトID]
```

　4.ブラウザを起動

```console:コマンドプロンプト
gcloud app browse --project [GCPのプロジェクトID]
```

　**【アクセス結果】**
　　ローカルサーバーで表示したときと同じ。

# 参考にしたサイト
・[Goスタンダード環境(Google公式)](https://cloud.google.com/appengine/docs/standard/go/building-app/creating-your-application)
・[net/httpパッケージ](https://golang.org/pkg/net/http/)
・[encoding/jsonパッケージ](https://golang.org/pkg/encoding/json/)
・[google.golang.org/appengineパッケージ](https://cloud.google.com/appengine/docs/standard/go/reference?hl=ja)
・[Googleの中の人が書いたソース](https://github.com/GoogleCloudPlatform/golang-samples/tree/8deb2909eadf32523007fd8fe9e8755a12c6d463/appengine/gophers/gophers-1)

# おわりに
コマンドを叩くだけでデプロイできたので、手間も少なく確実性が高くて良かったです。