LoginSignup
16
19

More than 5 years have passed since last update.

GoogleAppEngine/Goのインストールから使いやすくするとこまでをさくっと 後編

Last updated at Posted at 2016-03-06

インストールまでは前編参照。

後編もHelloWorldのソースを改良していく。

staticファイルの参照

このままだと、staticファイルを参照できないのでapp.yamlをいじる。

まずpublicフォルダを作成。(ここにstaticファイルを置くようにする)
スクリーンショット 2016-03-06 09.54.22.png

app.yaml
runtime: go
api_version: go1

handlers:
# -----------------------------ここから
# /終わりをindex.htmlへ変換(ルート)
- url: /$
  static_files: public/index.html
  upload: public/index.html

# /終わりをindex.htmlへ変換(内部)
- url: /(.*)/$
  static_files: public/\1/index.html
  upload: public/.*/index.html

# コンポーネントstaticファイル(.を含むとstaticと見做す)
- url: /bower_components/(.*)
  static_files: bower_components/\1
  upload: bower_components/.*

# staticファイル(.を含むとstaticと見做す)
- url: /([^\.]+\..*)
  static_files: public/\1
  upload: public/[^\.]+\..*
# -----------------------------ここまで追加
- url: /.*
  script: _go_app

簡単に解説すると、-urlから始まる3行1セットでルーティングをしていて、
1行目のパターンが来たら、3行目のパターンに変換していて、2行目がファイルの種類を表している、らしい。
(正規表現で書かれているので、詳しくない方は上記そのままコピペしてください)
これを入れると、/終わりのURLがindex.htmlに変換されて、拡張子を含むURLがstaticファイルとみなされる。
上から順にURLを処理するため、staticファイルではない→Goで処理と判断される。
【追記】
上記に加えて、bowerで取得したコンポーネントはbower_componentsを見るように変更(npmなどはbowerの部分を自分で書き換えてください)。

publicの中にindex.htmlを作成(今回はここのテンプレートを参照)

public/index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta charset="utf-8">
<meta name="description" content="">
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="">
<!--&#91;if lt IE 9&#93;>
<script src="//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
<!&#91;endif&#93;-->
<link rel="shortcut icon" href="">
</head>
<body>
<!-- Place your content here -->
Go の Staticファイルのテスト。
<!-- SCRIPTS -->
<!-- Example: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> -->
</body>
</html>

HelloWorldから書き換わったのを確認。
スクリーンショット 2016-03-06 10.10.43.png

Datastoreを使う(AppEngineのモジュールをインポート)

デフォルトだと何故かDatastoreなどのAppEngine関連のモジュールを使えないのでgo getを使ってインストール。
(MacやLinuxの場合は.batは不要)

bash
goapp.bat get google.golang.org/appengine

普通のgolangとGAE/Goのgolangは完全に独立して動くようにgoappになっているらしい。
(getした場合のインストール場所も違う)
何も指定しないとインストール場所は「go_appengine\gopath\src」になる。
(前編通りにやるとC:\go_appengine\gopath\src)
自分でコモン系のモジュールを作成した場合もここに置けば認識される。

hello.go
package hello

import (
    "fmt"
    "net/http"
    "time"//ここ追加
    "google.golang.org/appengine"//ここ追加
    "google.golang.org/appengine/datastore"//ここ追加
)

func init() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/put", putHandler)//ここ追加
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, world!")
}

//------------------------------------------------ここから
type Employee struct {
    Name string
    Role string
    HireDate time.Time
}

func putHandler(w http.ResponseWriter, r *http.Request) {
    ctx := appengine.NewContext(r)

    e1 := Employee{
        Name:     "Joe Citizen",
        Role:     "Manager",
        HireDate: time.Now(),
    }

    key, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "employee", nil), &e1)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    var e2 Employee
    if err = datastore.Get(ctx, key, &e2); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    fmt.Fprintf(w, "Stored and retrieved the Employee named %q", e2.Name)
}
//------------------------------------------------ここまで追加

スクリーンショット 2016-03-06 10.33.35.png
これでDatastoreが使用できる状態になった。

テンプレートを使う

サーバで作成したデータを出せないので、サーバ側のテンプレートを使えるようにする。

hello.go
package hello

import (
    "fmt"
    "net/http"
    "time"
    "html/template"//ここ追加
    "google.golang.org/appengine"
    "google.golang.org/appengine/datastore"
)

func init() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/put", putHandler)
    http.HandleFunc("/tmpl", tmplHandler)//ここ追加
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, world!")
}

//------------------------------------------------ここから
type TmplTest struct {
    Txt string
}
func tmplHandler(w http.ResponseWriter, r *http.Request) {
    tpl := template.Must(template.ParseFiles("tmpl/test.html"))

    data := TmplTest{
        Txt:  "Tmpl テスト",
    }

    tpl.Execute(w, data)
}
//------------------------------------------------ここまで追加

type Employee struct {
    Name string
    Role string
    HireDate time.Time
}

func putHandler(w http.ResponseWriter, r *http.Request) {
    ctx := appengine.NewContext(r)

    e1 := Employee{
        Name:     "Joe Citizen",
        Role:     "Manager",
        HireDate: time.Now(),
    }

    key, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "employee", nil), &e1)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    var e2 Employee
    if err = datastore.Get(ctx, key, &e2); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    fmt.Fprintf(w, "Stored and retrieved the Employee named %q", e2.Name)
}

テンプレート

tmpl/test.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta charset="utf-8">
<meta name="description" content="">
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="">
<!--&#91;if lt IE 9&#93;>
<script src="//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
<!&#91;endif&#93;-->
<link rel="shortcut icon" href="">
</head>
<body>
<!-- Place your content here -->
{{printf "%s" .Txt |html}}
<!-- SCRIPTS -->
<!-- Example: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> -->
</body>
</html>

スクリーンショット 2016-03-06 11.13.30.png
これでテンプレートを使って値を出力できた。

Goonを入れる

Goonを入れたほうが便利なのでGoonを使う。
この記事が分かりやすかったのでリンクさせてもらいました。
入れ方のみ。

bash
goapp.bat get github.com/mjibson/goon

終わりに

とりあえず、ここまでやれば、GAE/JにSlim3を入れたぐらいのことはできるようになると思います。

クライアント側のテンプレートやフレームワークが充実してきているので、
個人的にはサーバ側のテンプレートエンジンまではいらないかなとも思っています。

Javaの方は使っているのですが、私も、GAE/Goを入れたばかりなので、突っ込みどころは満載だと思います。
間違っていればコメントで指摘ください。

16
19
0

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
16
19