コード
template/base.html
{{define "base"}}<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{{template "title" .}}</title>
</head>
<body>
<div class="content">
{{template "body" .}}
</div><!-- /.content -->
</body>
</html>{{end}}
template/view.html
{{define "title"}}{{.Title}}{{end}}
{{define "body"}}
<h1>{{.Title}}</h1>
<article>
{{.Body|safehtml}}
</article>
{{end}}
templatetest.go
package main
import (
"html/template"
"net/http"
)
func viewHandler(w http.ResponseWriter, r *http.Request) {
funcMap := template.FuncMap{
"safehtml": func(text string) template.HTML { return template.HTML(text) },
}
templates := template.Must(template.New("").Funcs(funcMap).ParseFiles("templates/base.html",
"templates/view.html"))
dat := struct {
Title string
Body string
}{
Title: "メイジェイって",
Body: "いっつも<b>ありのまま</b>だよね",
}
err := templates.ExecuteTemplate(w, "base", dat)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func main() {
http.HandleFunc("/", viewHandler)
http.ListenAndServe(":8080", nil)
}
go run templatetest.go
して ブラウザで http://localhost:8080
を開く。
ポイント
-
template.FuncMap{}
とtemplate.Funcs()
でテンプレート中で使える独自メソッドをテンプレート側に登録しているところ。
template/view.html の{{.Body|safehtml}}
で使ってる -
ネスト対象の子テンプレートを
template.ParseFiles("templates/base.html", "templates/view.html")
で読み込んでいるところ。
-
templates.ExecuteTemplate(w, "base", dat)
で、一番大きな範囲の
base
だけを明示的に指定しているところ。
メモ
Go では var := template.HTML(var)
することで、
Django での var = mark_safe(var)
みたいなことが出来る。
ただ、このままだと、
例えば DB に保存する場合に型の違いを処理しないといけなかったりして、
そうじゃなくて、出力時だけ生で出力する、
Django や Jinja2 での {{var|safe}}
みたいな仕組みが欲しかった。
ちなみに html/template
じゃなくて text/template
を使うと自動エスケープを気にしなくて良くなる感じだった。この場合、必要なところだけ html.EscapeString()
でエスケープ出来るが、せっかく安全側に倒してくれる仕組みを言語のほうで用意してくれているので、そっちの恩恵にあずかりたかった。
下記を参考にさせて頂いた。
- html/templateでテンプレートを継承する - YAMAGUCHI::weblog
- go - Template and custom function; panic: function not defined - Stack Overflow
- build-web-application-with-golang/07.4.md at master · astaxie/build-web-application-with-golang · GitHub
ちなみに html - GoDoc を見ると func UnescapeString(s string) string
なんてものもあるみたい。