[Go言語] templateパッケージでtwigとかのextends的なあれをやるにはどうしようか
September 29, 2013
この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。
やりたいこと
twigでいくと以下のようなやつ。 でも、デフォルトがあってそれを上書きするとかいう機能は別にいらない。 共通部分を使い回せればそれでいい。
参考:http://twig.sensiolabs.org/doc/tags/extends.html
<!DOCTYPE html>
<html>
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2011 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ parent() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome on my awesome homepage.
</p>
{% endblock %}
やってみた
とりあえず、PlayGroundでやってみた。
http://play.golang.org/p/YQd6ChZFqd
package main
import (
"fmt"
"os"
"text/template"
)
var layoutStr = `{{define "layout"}}header
{{template "content"}}
footer{{end}}`
var hogeStr = `{{define "content"}}hoge{{end}}`
var piyoStr = `{{define "content"}}piyo{{end}}`
func main() {
hoge := template.Must(template.New("hoge").Parse(hogeStr))
hoge.Parse(layoutStr)
hoge.ExecuteTemplate(os.Stdout, "layout", nil)
fmt.Println()
piyo := template.Must(template.New("piyo").Parse(piyoStr))
piyo.Parse(layoutStr)
piyo.ExecuteTemplate(os.Stdout, "layout", nil)
}
もっとちゃんとやってみた
https://github.com/golang-samples/template/tree/master/extends
baseを作る
まずは、baseとなるhtmlを作る。
テンプレートの名前は、base
としておく。
template
でcontent
という別のテンプレートを読み込んでいる。
{{define "base"}}
<!DOCTYPE html>
<html>
<body>
<header>
<h1>Title of {{.}}</h1>
<nav>
<ul>
<li><a href="hoge">Hoge</a></li>
<li><a href="piyo">Piyo</a></li>
</ul>
</nav>
</header>
<article id="content">
{{template "content" .}}
</article>
<footer>
© Copyright 2013 by golang-samples.
</footer>
</body>
</html>
{{end}}
コンテンツを作る
続いて、コンテンツとなるhtmlを作る。
base.html
に埋め込まれるので、テンプレートの名前は2つともcontent
にしておく。
{{define "content"}}
<h1>Hoge</h1>
<p>
I'm Hoge.
</p>
{{end}}
{{define "content"}}
<h1>Piyo</h1>
<p>
I'm Piyo.
</p>
{{end}}
Goから読み込む
以下のように、別々のテンプレートとしてパースすることで、content
という名前が被ってもできる。もちろん、ParseGlob
とかで一気にパースするとダメ。
ベースで指定した部分を上書きするtwigのextendsの方が自由度高いが、まぁコレくらいできたら別にいいや。
package main
import (
"html/template"
"net/http"
)
var hogeTmpl = template.Must(template.New("hoge").ParseFiles("base.html", "hoge.html"))
func hogeHandler(w http.ResponseWriter, r *http.Request) {
hogeTmpl.ExecuteTemplate(w, "base", "Hoge")
}
var piyoTmpl = template.Must(template.New("piyo").ParseFiles("base.html", "piyo.html"))
func piyoHandler(w http.ResponseWriter, r *http.Request) {
piyoTmpl.ExecuteTemplate(w, "base", "Piyo")
}
func main() {
// hoge
http.HandleFunc("/", hogeHandler)
http.HandleFunc("/hoge", hogeHandler)
// piyo
http.HandleFunc("/piyo", piyoHandler)
http.ListenAndServe(":8080", nil)
}