[Go言語] templateパッケージでtwigとかのextends的なあれをやるにはどうしようか

# やりたいこと
twigでいくと以下のようなやつ。
でも、デフォルトがあってそれを上書きするとかいう機能は別にいらない。
共通部分を使い回せればそれでいい。

参考：http://twig.sensiolabs.org/doc/tags/extends.html

``` base.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 %}
                &copy; Copyright 2011 by <a href="http://domain.invalid/">you</a>.
            {% endblock %}
        </div>
    </body>
</html>
```

``` child.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

```main.go
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`という別のテンプレートを読み込んでいる。

```base.html
{{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>
        &copy; Copyright 2013 by golang-samples.
      </footer>
    </body>
</html>
{{end}}
```

## コンテンツを作る

続いて、コンテンツとなるhtmlを作る。
`base.html`に埋め込まれるので、テンプレートの名前は2つとも`content`にしておく。

```hoge.html
{{define "content"}}
<h1>Hoge</h1>
<p>
  I'm Hoge.
</p>
{{end}}
```

```piyo.html
{{define "content"}}
<h1>Piyo</h1>
<p>
  I'm Piyo.
</p>
{{end}}
```

## Goから読み込む

以下のように、別々のテンプレートとしてパースすることで、`content`という名前が被ってもできる。もちろん、`ParseGlob`とかで一気にパースするとダメ。

ベースで指定した部分を上書きするtwigのextendsの方が自由度高いが、まぁコレくらいできたら別にいいや。

```main.go
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)
}
```