データの保存(GAE/Go/Gin)

#はじめに
GAEをGinを利用して構築していきます。
[HTML フォームデータの処理(GAE/Go/Gin)](https://qiita.com/koshi_an/items/c0979707de9e8ef7cb9b)の続きです。

流れは、公式サイトの[データの保存](https://cloud.google.com/appengine/docs/standard/go/building-app/storing-data?hl=ja)と同じです。


#ソース

今回のフォルダ構成は、以下の通りです。

```
├──  template
│    └── index.html
├──  static
│    ├── style.css
│    └── gcp-gopher.svg
├──  app.yaml
└──  main.go
```

```yaml:app.yaml
runtime: go111

handlers:
- url: /static
  static_dir: static
  
- url: /.*
  script: auto
```

```css:style.css
body {
    font-family: Arial, sans-serif;
    color: blue;
  }
```

Ginを利用しており、GETメソッドと POSTメソッドで呼び出すハンドラーを分けています。

```go:main.go
package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"google.golang.org/appengine"
	"google.golang.org/appengine/datastore"
	"google.golang.org/appengine/log"
)

type Post struct {
	Author  string
	Message string
	Posted  time.Time
}

type templateParams struct {
	Notice  string
	Name    string
	Message string
	Posts   []Post
}

func main() {
	router := gin.Default()

	router.LoadHTMLGlob("template/*") // 事前にテンプレートをロード(相対パス)

	router.GET("/", indexGetHandle)
	router.POST("/", indexPostHandle)

	http.Handle("/", router) // router.Run(":8080")の代わり
	appengine.Main()         // これがないと動かない
}

func indexGetHandle(c *gin.Context) {

	ctx := appengine.NewContext(c.Request)
	params := templateParams{}

	q := datastore.NewQuery("Post").Order("-Posted").Limit(20)
	if _, err := q.GetAll(ctx, &params.Posts); err != nil {
		log.Errorf(ctx, "Getting posts: %v", err)
		params.Notice = "Couldn't get latest posts. Refresh?"

		c.HTML(http.StatusInternalServerError, "top/index", gin.H{
			"params": params,
		})
		return
	}

	c.HTML(http.StatusOK, "top/index", gin.H{
		"params": params,
	})
}

func indexPostHandle(c *gin.Context) {

	ctx := appengine.NewContext(c.Request)
	params := templateParams{}

	post := Post{
		Author:  c.PostForm("name"),
		Message: c.PostForm("message"),
		Posted:  time.Now(),
	}

	if post.Author == "" {
		post.Author = "Anonymous Gopher"
	}
	params.Name = post.Author

	if post.Message == "" {
		params.Notice = "No message provided"

		c.HTML(http.StatusBadRequest, "top/index", gin.H{
			"params": params,
		})
		return
	}

	key := datastore.NewIncompleteKey(ctx, "Post", nil)

	if _, err := datastore.Put(ctx, key, &post); err != nil {
		log.Errorf(ctx, "datastore.Put: %v", err)

		params.Notice = "Couldn't add new post. Try again?"
		params.Message = post.Message // Preserve their message so they can try again.

		c.HTML(http.StatusInternalServerError, "top/index", gin.H{
			"params": params,
		})
		return
	}

	params.Posts = append([]Post{post}, params.Posts...)

	params.Notice = fmt.Sprintf("Thank you for your submission, %s!", post.Author)

	c.HTML(http.StatusOK, "top/index", gin.H{
		"params": params,
	})
}
```

変数指定で、「.params」がないと動作しませんでした。

```html:template/index.html
{{ define "top/index" }}
<!doctype html>
<html>
<head>
  <title>The Gopher Network</title>
  <link rel="stylesheet" type="text/css" href="/static/style.css">
</head>
<body>

<h1>The Gopher Network</h1>

<img id="logo" src="/static/gcp-gopher.svg" width="100">

{{with .params.Notice}}<div id="notice">{{.}}</div>{{end}}

<form action="/" method="post">
  <div>Name: <input name="name" value="{{.params.Name}}"></div>
  <div>Message: <input name="message"></div>
  <input type="submit">
</form>

{{with .params.Posts}}
<ol>
  {{range . }}
  <li><cite>{{.Author}}</cite><p>{{.Message}}</p></li>
  {{end}}
</ol>
{{end}}

</body>
</html>
{{ end }}
```


#ローカルで実行
`dev_appserver.py app.yaml`

`localhost:8080`  にアクセスすると以下の画面が表示されます。

![スクリーンショット 2019-07-07 16.40.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125499/7d57b19b-8dd7-5503-3ef8-b0f3b582e036.png)

![スクリーンショット 2019-07-07 16.55.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125499/4c5030c5-a568-33a5-b1d8-c96571d5844b.png)

データは、どこに登録されれいるのだろう？？

#アプリケーションをデプロイする

`gcloud app deploy`


#アプリケーションを表示する

`gcloud app browse`


その後、`http://[YOUR_PROJECT_ID].appspot.com`で、画面が表示されるかを確認します。

![スクリーンショット 2019-07-07 17.06.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125499/f40c1159-b72a-8e6b-b148-b7db9742885e.png)


メッセージ送付後

![スクリーンショット 2019-07-07 17.07.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125499/c26e7384-b3ef-22f5-decd-a05ffb092742.png)

データは、Datastoreに保存されてました。

![スクリーンショット 2019-07-07 17.17.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125499/d2cb8c41-47b0-c365-2c18-bc64171e7829.png)

**ローカル起動時のデータが何処に保存されているのか不明**


#参考
[データの保存](https://cloud.google.com/appengine/docs/standard/go/building-app/storing-data?hl=ja)