LoginSignup
3
2

More than 5 years have passed since last update.

Go Web Examplesの和訳(Templates)

Posted at

Go勉強会 Webアプリケーション編 #2で使おうと思っているGo Web Examplesの和訳です。ほぼGoogle翻訳ですが、リンク等も整理された状態であると便利だと思い作りました。次回(Requests & Forms)


はじめに

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

ファイルからのテンプレート解析

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

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が設定されます。

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>
3
2
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
3
2