Go Web Examplesの和訳（Templates）

[Go勉強会 Webアプリケーション編 #2](https://go-golang.connpass.com/event/102366/)で使おうと思っている[Go Web Examples](https://gowebexamples.com/templates/)の和訳です。ほぼGoogle翻訳ですが、リンク等も整理された状態であると便利だと思い作りました。[次回（Requests & Forms）](https://qiita.com/miyamoto_ta/items/39953e793757a7fab667)

---

## はじめに
Goの[html/template](https://golang.org/pkg/html/template/)パッケージはHTMLテンプレート用の豊富なテンプレート言語を提供します。主にWebアプリケーションで使用され、クライアントのブラウザで構造化データを表示します。Goのテンプレート言語の大きな利点の1つは、データを自動でエスケープすることです。GoはHTMLテンプレートを解析し、すべての入力をエスケープしてからブラウザに表示するので、XSS攻撃については心配する必要はありません。

## 最初のテンプレート
Goのテンプレートの書き方は非常にシンプルです。この例では、HTMLの順序付けられていないリスト(ul)として記述されたTODOリストを示しています。レンダリングテンプレートの場合、渡されるデータはあらゆる種類のGoのデータ構造になります。これは単純な文字列または数値でもよく、下の例のようにネストされたデータ構造でも可能です。テンプレート内でデータにアクセスするには、変数の先頭を `{{.}}` にしてアクセスします。中括弧内のドットはパイプラインとデータのルート要素と呼ばれます。

```go
data := TodoPageData{
	PageTitle: "My TODO list",
	Todos: []Todo{
		{Title: "Task 1", Done: false},
		{Title: "Task 2", Done: true},
		{Title: "Task 3", Done: true},
	},
}
```

```html

<h1>{{.PageTitle}}<h1>
<ul>
    {{range .Todos}}
        {{if .Done}}
            <li class="done">{{.Title}}</li>
        {{else}}
            <li>{{.Title}}</li>
        {{end}}
    {{end}}
</ul>
```

## 制御構造
テンプレート言語には、HTMLをレンダリングするための豊富なコントロール構造が含まれています。ここでは、最も一般的に使用されるものの概要を紹介します。すべての可能な構造の詳細なリストを入手するには[text/template](https://golang.org/pkg/text/template/#hdr-Actions)を参照してください。

| 制御構造                       | 定義                                                  |
|:------------------------------|:-----------------------------------------------------|
| {{/* a comment */}}           |コメントを定義します                                        |
| {{.}}                         |ルート要素をレンダリングします                                |
| {{.Title}}	                |ネストされた要素の"Title"フィールドをレンダリングします            |
| {{if .Done}} {{else}} {{end}} |if-statementを定義します                                 |
| {{range .Todos}} {{.}} {{end}}|すべての"Todos"をループし`{{.}}`を利用してそれらをレンダリングします|
| {{block "content" .}} {{end}}	|"content"という名前のブロックを定義します                      |

## ファイルからのテンプレート解析
テンプレートは、文字列やディスク上のファイルから解析することができます。通常の場合、テンプレートはディスクからのpares(※parseのtypo？)です。この例では、その方法を示しています。この例では、Goプログラムと同じディレクトリにテンプレートファイル`layout.html`があります。

```go
tmpl, err := template.ParseFiles("layout.html")
// or
tmpl := template.Must(template.ParseFiles("layout.html"))
```

## Request Handler 内でテンプレートを実行する
テンプレートがディスクから解析されると、そのテンプレートはリクエストハンドラ内で使用できる状態になります。
`Execute`関数はテンプレートを書き込むための`io.Writer`とテンプレートにデータを渡すための`interface {}`を受け入れます。
関数が`http.ResponseWriter`で呼び出されると、Content-Typeヘッダには自動で`Content-Type: text/html; charset=utf-8`が設定されます。

```go
func(w http.ResponseWriter, r *http.Request) {
	tmpl.Execute(w, "data goes here")
}
```

## コピペ用コード
これは、この例で学んだことを試すために使用できる完全なコードです。

```go
package main

import (
	"html/template"
	"net/http"
)

type Todo struct {
	Title string
	Done  bool
}

type TodoPageData struct {
	PageTitle string
	Todos     []Todo
}

func main() {
	tmpl := template.Must(template.ParseFiles("layout.html"))

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		data := TodoPageData{
			PageTitle: "My TODO list",
			Todos: []Todo{
				{Title: "Task 1", Done: false},
				{Title: "Task 2", Done: true},
				{Title: "Task 3", Done: true},
			},
		}
		tmpl.Execute(w, data)
	})

	http.ListenAndServe(":80", nil)
}
```

```html
<h1>{{.PageTitle}}<h1>
<ul>
    {{range .Todos}}
        {{if .Done}}
            <li class="done">{{.Title}}</li>
        {{else}}
            <li>{{.Title}}</li>
        {{end}}
    {{end}}
</ul>
```