Go Web Examples - Templatesの和訳です。リンク等が整理された状態で和訳があると便利だと思い作りました。前回(Routing (using gorilla/mux))。
はじめに
Goのhtml/templateパッケージは、HTMLテンプレート用の豊富なテンプレート言語を提供します。主にWebアプリケーションで使用され、クライアントのブラウザで構造化された方法でデータを表示します。Goのテンプレート言語の大きな利点の1つは、データの自動エスケープです。 GoはHTMLテンプレートを解析し、すべての入力をエスケープしてからブラウザに表示するので、XSS攻撃については心配する必要はありません。
はじめのテンプレート
Goにテンプレートを書くのはとても簡単です。 この例では、HTMLの順序付けられていないリスト(ul)として記述されたTODOリストを示しています。 レンダリングテンプレートの場合、渡されるデータはあらゆる種類のGoのデータ構造になります。 これは単純な文字列または数値でもよく、下の例のようにネストされたデータ構造でも可能です。 テンプレートのデータにアクセスするには、一番上の変数は{{.}}
でアクセスします。 中括弧内の点は、パイプラインとデータのルート要素と呼ばれます。
data := TodoPageData{
PageTitle: "My TODO list",
Todos: []Todo{
{Title: "Task 1", Done: false},
{Title: "Task 2", Done: true},
{Title: "Task 3", Done: true},
},
}
<h1>{{.PageTitle}}<h1>
<ul>
{{range .Todos}}
{{if .Done}}
<li class="done">{{.Title}}</li>
{{else}}
<li>{{.Title}}</li>
{{end}}
{{end}}
</ul>
制御構造
テンプレート言語には、HTMLをレンダリングするための豊富な制御構造が含まれています。 ここでは、最も一般的に使用されるものの概要を紹介します。 すべての可能な構造の詳細なリストを入手するにはtext/templateを参照ください。
制御構造 | 定義 |
---|---|
{{/* a comment */}} | コメント定義 |
{{.}} | ルート要素をレンダリング |
{{.Title}} | ネストされた要素の "Title"フィールドをレンダリング |
{{if .Done}} {{else}} {{end}} | if文の定義 |
{{range .Todos}} {{.}} {{end}} | すべての "Todos"をループし、{{.}} でレンダリング |
{{block "content" .}} {{end}} | "content"という名前のブロックを定義 |
ファイルからのテンプレートのパーズ
テンプレートは、文字列やディスク上のファイルからパーズすることができます。 通常の場合、テンプレートはディスクからパーズされます。この例ではその方法を示しています。(layout.html
というテンプレートファイルがGoプログラムと同じディレクトリにあります。)
tmpl, err := template.ParseFiles("layout.html")
// or
tmpl := template.Must(template.ParseFiles("layout.html"))
リクエストハンドラでテンプレートを実行する
テンプレートがディスクからパーズされると、そのテンプレートはリクエストハンドラで使用できる状態になります。 Execute関数は、テンプレートを書き込むためのio.Writer
とテンプレートにデータを渡すためのinterface{}
を受け入れます。 関数がhttp.ResponseWriter
で呼び出されると、HTTPレスポンスのContent-Typeヘッダーに自動的にContent-Type: text/html; charset=utf-8
が設定されます。
func(w http.ResponseWriter, r *http.Request) {
tmpl.Execute(w, "data goes here")
}
コード(コピペ用)
これは、この例で学んだことを試すために使用できる完全なコードです。
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)
}
<h1>{{.PageTitle}}<h1>
<ul>
{{range .Todos}}
{{if .Done}}
<li class="done">{{.Title}}</li>
{{else}}
<li>{{.Title}}</li>
{{end}}
{{end}}
</ul>