Go Web Examplesの和訳 （Templates）

[Go Web Examples - Templates](https://gowebexamples.com/templates/)の和訳です。リンク等が整理された状態で和訳があると便利だと思い作りました。[前回（Routing (using gorilla/mux)）](https://qiita.com/tikidunpon/items/b3a926d9146d55eb0848)。

# はじめに

Goの[html/template](https://golang.org/pkg/html/template/)パッケージは、HTMLテンプレート用の豊富なテンプレート言語を提供します。主にWebアプリケーションで使用され、クライアントのブラウザで構造化された方法でデータを表示します。Goのテンプレート言語の大きな利点の1つは、データの自動エスケープです。 GoはHTMLテンプレートを解析し、すべての入力をエスケープしてからブラウザに表示するので、[XSS攻撃](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0)については心配する必要はありません。

# はじめのテンプレート  

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文の定義  | 
| {{range .Todos}} {{.}} {{end}} | すべての "Todos"をループし、{{.}} でレンダリング | 
| {{block "content" .}} {{end}} | "content"という名前のブロックを定義 | 

# ファイルからのテンプレートのパーズ

テンプレートは、文字列やディスク上のファイルからパーズすることができます。 通常の場合、テンプレートはディスクからパーズされます。この例ではその方法を示しています。（`layout.html`というテンプレートファイルがGoプログラムと同じディレクトリにあります。）

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

- [docs: html/template/ParseFiles](https://golang.org/pkg/html/template/#ParseFiles)
- [docs: html/template/Must](https://golang.org/pkg/html/template/#Must)

# リクエストハンドラでテンプレートを実行する  

テンプレートがディスクからパーズされると、そのテンプレートはリクエストハンドラで使用できる状態になります。 [Execute関数](https://golang.org/pkg/html/template/#Template.Execute)は、テンプレートを書き込むための`io.Writer`とテンプレートにデータを渡すための`interface{}`を受け入れます。 関数が`http.ResponseWriter`で呼び出されると、HTTPレスポンスの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>
```