LoginSignup
1

More than 3 years have passed since last update.

Google App Engine で始める Go 実践入門 Part 6 【Hello World】

Last updated at Posted at 2019-03-31

連載を通して簡単なブログアプリを作成しつつ Go/GAE について学んでいきます。
今回は Hello World を出力してみます。

パッケージ管理ツール 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

ファイルにコードを書いていきます。

modue/blog/handler/hello_handler.go
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)
}
modue/blog/main/app.go
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)
}
modue/blog/main/app-engine.go
// +build appengine

package main

import (
    "net/http"

    "github.com/labstack/echo"
)

func createMux() *echo.Echo {
    e := echo.New()

    http.Handle("/", e)

    return e
}
modue/blog/main/app-standalone.go
// +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"))
}
module/blog/main/app.yaml
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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1