2019年2月22日金曜日

GAE + golang 入門

概要

過去に Ruby で GAE に入門しました
このときは Flexible Environment という新しい環境を試しました
今回は Standard Environment という昔からあるランタイムを指定する環境を使ってみたいと思います
ちなみに Always free の範囲はこの Standard Environment になります
gcloud コマンドや GCP のサインアップなどは事前に済ませておいてください

環境

  • macOS 10.14.3
  • gcloud 234.0

app-engine-go のインストール

  • gcloud components install app-engine-go
  • ln -s /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/bin/dev_appserver.py /usr/local/bin/dev_appserver.py

必要なのは下の Python スクリプトです
これを使ってローカルでテストすることができます

また $GOPATH/src/google.golang.org/appengine というライブラリがあることも確認しましょう

とりあえず Hello World してみる

GAE で動作するサンプルアプリがあるのでそれを取得してサクっとデプロイしてみます

  • go get -u -d github.com/GoogleCloudPlatform/golang-samples/appengine/helloworld/...
  • cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples/appengine/helloworld/

まずはローカルでチェックします

  • dev_appserver.py app.yaml

localhost:8080 にアクセスして Hello World が表示されることを確認します
ローカルで動作することがわかったら GAE にデプロイしてみましょう

  • gcloud app deploy
Initializing App Engine resources...done.                                                                                      
Services to deploy:

descriptor:      [/Users/hawksnowlog/go/src/github.com/GoogleCloudPlatform/golang-samples/appengine/helloworld/app.yaml]
source:          [/Users/hawksnowlog/go/src/github.com/GoogleCloudPlatform/golang-samples/appengine/helloworld]
target project:  [hawksnowlog-123456]
target service:  [default]
target version:  [20190219t153345]
target url:      [https://hawksnowlog-123456.appspot.com]


Do you want to continue (Y/n)?

ちゃんと確認画面がでます
問題なければ Y でデプロイしましょう

Web ページを配置する

このままだと何もないのでコンテンツでも配置してみます
まず index.html を作成します

  • touch index.html
  • vim index.html
<html>
  <head>
    <title>Image Contents</title>
  </head>
  <body>
    <img src="{{.Src}}">
  </body>
</html>

画像を表示するだけの HTML です
画像の URL の部分を変数にしておりこの変数を go アプリ側で設定します

作成した index.html を描画するための go アプリを作成します
コード全体は以下の通りです

  • vim main.go
package main

import (
    "html/template"
    "math/rand"
    "net/http"
    "time"

    "google.golang.org/appengine"
)

var (
    index = template.Must(template.ParseFiles("index.html"))
)

type params struct {
    Src string
}

func main() {
    http.HandleFunc("/", handle)
    appengine.Main()
}

func handle(w http.ResponseWriter, r *http.Request) {
    params := params{}
    images := [3]string{
        "https://blog.golang.org/gopher/header.jpg",
        "https://blog.golang.org/gopher/wfmu.jpg",
        "https://blog.golang.org/gopher/glenda.png",
    }
    rand.Seed(time.Now().Unix())
    params.Src = images[rand.Intn(len(images))]
    index.Execute(w, params)
}

少し解説

まずテンプレートファイルを読み込みます
"html/template" が必要になるので import しておきましょう

var (
    index = template.Must(template.ParseFiles("index.html"))
)

このテンプレートファイルを Execute することで HTML を描画できます
Execute はハンドラメソッド内で行っています
テンプレートを描画する際にパラメータを渡すことでテンプレート内の変数を展開することができます
テンプレート内で使用している変数を持つ構造体を宣言します

type params struct {
    Src string
}

ハンドラ内でこの構造体を生成し変数に画像の URL を設定しています
せっかくなので画像は 3 つのうちからランダムで取得するようにしています
ランダムの部分は調べればいろいろ出ると思います
今回は "math/rand" を使った方式で配列からランダムで取得しています

デプロイ

  • dev_appserver.py app.yaml

で確認したら

  • gcloud app deploy

で GAE にデプロイしましょう
アクセスするとローカルで動かしたように画像がランダムに表示されるのが確認できると思います

おまけ: CSS も当ててみる

当然 Web ページであれば CSS も必要になります

  • vim app.yaml
runtime: go
api_version: go1

handlers:
- url: /static
  static_dir: static
- url: /.*
  script: _go_app

静的コンテンツを配信するハンドラを 1 つ追加します
ポイントは先に /static のハンドラを定義するところです
こうしないと /.* が先に評価されてしまいうまく CSS を配信できません

  • mkdir static
  • touch static/style.css
  • vim static/style.css
.image {
    width: 100%;
    text-align: center;
}

あとは index.html を修正します
スタイルシートを参照するように変更します

<html>
  <head>
    <title>Image Contents</title>
    <link rel="stylesheet" type="text/css" href="/static/style.css">
  </head>
  <body>
    <div class="image">
      <img src="{{.Src}}">
    </div>
  </body>
</html>

これだけです
あとは同じようにデプロイすればスタイルシートが適用されたページが表示されます

おまけ: その他 Tips

ロギングや httpClient を使う場合には ctx := appengine.NewContext(r) を使う
パッケージは google.golang.org/appengine

普通の httpClient は使えないので urlfetch.Client(ctx) を使う
パッケージは google.golang.org/appengine/urlfetch

favicon.ico を使いたい場合は app.yaml に以下を追加する
また static/favicon.ico を配置する

- url: /favicon\.ico
  static_files: static/favicon.ico
  upload: static/favicon\.ico

http をすべて https にリダイレクトするには secure: always を使う

- url: /.*
  script: _go_app
  secure: always

最後に

GAE の Standard Environment に golang で入門しました
GAE で動かすためのライブラリが必要なので既存のアプリだと変更する点は多そうです
開発するためのツールは揃っているので導入障壁は低いと思います

このあとはデータを保存したりするチュートリアルもあるので、そのまま進めれば最低限必要な知識は揃うと思います

参考サイト

0 件のコメント:

コメントを投稿