連載を通して簡単なブログアプリを作成しつつ Go/GAE について学んでいきます。
今回は Hello World を出力してみます。
- Part 1. 『GO / Cloud SDK のインストール』
- Part 2. 『GOPATH』
- Part 3. 『プロジェクトの作成』
- Part 4. 『ディレクトリ構成』
- Part 5. 『Visual Studio Code』
- Part 6. 『Hello World』 ← イマココ
- Part 7. 『リモートデバッグ』
- Part 8. 『デプロイ』
- Part 9. 『Makefile』
- Part 10. 『Circle CI』
- Part 11. 『Dependency Injection』
- Part 12. 『ローカルDB with Docker』
- Part 13. 『gorm』
- Part 14. 『Cloud SQL』
- Part 15. 『Cloud SQL Proxy』
- Part 16. 『HTML』
- Part 17. 『CSS/JS』
- Part 18. 『Google Analytics』
- Part 19. 『Google Search Console』
- Part 20. 『A/B テスト』
- Part 21. 『ユーザーの作成』
- Part 22. 『Firebase Auth』
- Part 23. 『記事の作成』
- Part 24. 『コメントの作成』
- Part 25. 『ページネーション』
パッケージ管理ツール dep のインストール
パッケージ管理ツールとして今回は dep
を採用します。
Go 1.11 から導入された go mod
でもいいとは思いますが、今回は dep
で。
dep
は次のコマンドでインストールします。カレントディレクトリの位置はどこでも構いません。
go get -u -v github.com/golang/dep/cmd/dep
次にパッケージ管理の初期化を行います。ディレクトリ名は自分のもので読み替えてください。
# プロジェクトルートに移動
cd $GOPATH/src/github.com/rema424/go-gae-blog-app-example
# パッケージ管理の初期化
dep init
ここまでが完了すると、 GOPATH 配下は次のようになっているかと思います。
$GOPATH
├── bin
│ └── dep
└── src
└── github.com
├── golang
│ └── dep
└── rema424
└── go-gae-blog-app-example
├── vendor
├── .gitignore
├── Gopkg.lock
├── Gopkg.toml
└── README.md
Hello World
ウェブフレームワークには Echo を採用します。
Echo のガイドに App Engine を利用する場合のレシピが載っているので参考にします。
Google App Engine Recipe | Echo
以下、ターミナルでの作業はプロジェクトルートで行っていきます。
# ディレクトリ移動
cd $GOPATH/src/rema424/go-gae-blog-app-example
# ディレクトリ作成
mkdir -p module/blog/main module/blog/handler
# ディレクトリ移動
cd module/blog/main
# ファイル作成
touch app.yaml app.go app-engine.go app-standalone.go
# ディレクトリ移動
cd ../handler
# ファイル作成
touch hello_handler.go
この時点でのディレクトリ構成は次の通りです。
go-gae-blog-app-example
├── .vscode
│ └── settings.json
└── module
├── blog
│ ├── handler
│ │ └── hello_handler.go
│ └── main
│ ├── app-engine.go
│ ├── app-standalonde.go
│ ├── app.go
│ └── app.yaml
├── vendor
├── .gitignore
├── Gopkg.lock
├── Gopkg.toml
└── README.md
ファイルにコードを書いていきます。
package handler
import (
"net/http"
"github.com/labstack/echo"
)
type (
// Response ...
Response struct {
Message string
}
)
// HelloHandler ...
func HelloHandler(c echo.Context) error {
message := "Hello World!"
res := &Response{
Message: message,
}
return c.JSON(http.StatusOK, res)
}
// ParrotHandler ...
func ParrotHandler(c echo.Context) error {
message := c.Param("message")
res := &Response{
Message: message,
}
return c.JSON(http.StatusOK, res)
}
package main
import (
"github.com/rema424/go-gae-blog-app-example/module/blog/handler"
)
var e = createMux()
func init() {
e.GET("/", handler.HelloHandler)
e.GET("/:message", handler.ParrotHandler)
}
// +build appengine
package main
import (
"net/http"
"github.com/labstack/echo"
)
func createMux() *echo.Echo {
e := echo.New()
http.Handle("/", e)
return e
}
// +build !appengine
package main
import (
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
func createMux() *echo.Echo {
e := echo.New()
e.Use(middleware.Recover())
e.Use(middleware.Logger())
e.Use(middleware.Gzip())
return e
}
func main() {
e.Logger.Fatal(e.Start(":8080"))
}
runtime: go
api_version: go1.9
handlers:
- url: /.*
script: _go_app
inbound_services:
- warmup
Go の Build Constraints
(もしくは Build Tag
) と呼ばれる機能を使っています。
これにより App Engine 環境でもその他の環境でも動作するコードになっています。
Build に関する機能を使っているためアプリケーションの動作にはビルドが必要です。
go run
での起動はできないことに注意です。
ソースコードが出来上がったら次に関連モジュールを dep
でインストールしていきます。
dep
はソースコード上で import ブロックに記載されたモジュールを一括でインストールします。
# ディレクトリ移動
cd $GOPATH/src/rema424/go-gae-blog-app-example
# モジュールのインストール
dep ensure -v
モジュールが vendor
ディレクトリ配下にインストールされているのが分かるかと思います。
これらモジュールは git 管理する必要はないので、.gitignore
に vendor を追加します。
echo 'vendor' >> .gitignore
それではローカル PC 環境でアプリケーションを起動します。
# app.yaml のあるモジュールルートに移動
cd module/blog/main/
# ビルドを実行
go build
# バイナリを実行
./main
アプリケーションが起動するので、ブラウザで localhost:8080
にアクセスすると Hello World! が表示されるはずです。
App Engine ローカル開発サーバーの起動
App Engine はローカル開発サーバーを提供しています。
これにより「ローカルでは動いていたのに App Engine にデプロイしたら動かなかった」という可能性を小さくすることが可能となっています。
dev_appserver.py module/blog/main/app.yaml
サーバーが立ち上がるので、localhost:8080
にアクセスすると Hello World! が表示されます。
以降の開発は App Engine ローカル開発サーバーで行うと良いでしょう。ホットリロード機能も付いています。
dev_appserver.py
でサーバーを起動すると、同時に Cloud Datastore Emulator も起動されます。
今回は Cloud Datastore は使わないので、次のようなオプションを指定することによりサーバーの起動を速めることができます。
dev_appserver.py module/blog/main/app.yaml --support_datastore_emulator=False
--support_datastore_emulator=False
なしで起動すると、 app.yaml
と同じディレクトリに index.yaml
というファイルが自動生成されますが、 Cloud Datastore は使わないので削除しておきましょう。削除しておかないと後のデプロイの工程で失敗します。
dev_appserver.py
ではなく goapp serve
コマンドでも同様にサーバーを起動することができます。
goapp serve module/blog/main/app.yaml
goapp serve
コマンドは dev_appserver.py
のラッパーになっています。
ただし、オリジナルの dev_appserver.py
よりも利用できるオプションが少ないので goapp
は基本的には使わなくて良いかと思います。
例えば、サーバー起動時に環境変数を渡すといったことが dev_appserver.py
ではできますが goapp serve
ではできません。
App Engine のローカル開発サーバーはホスト OS 上で export された環境変数は読み込みません。環境変数を利用するためにはサーバー起動時にオプションで渡すか、 app.yaml
ファイルに記載するかのどちらかになります。
しかし、GitHub にアップできないような情報に対して環境変数を使いたいので、GitHub で管理したい app.yaml
には環境変数は定義できません。したがって、必然的に goapp
ではなく dev_appserver.py
を使うことになるかと思います。
おわりに
次回のテーマは『リモートデバッグ』です。
よかったら Twitter フォローしてね。@_rema424