Go言語によるWebサーバー作成入門 ーテンプレートー5
(作成2020.10.22)
前回の記事はこちら
テンプレートのテンプレート
ディレクトリ構成は次のようにしています。テンプレートを保存するディレクトリを作成して、メインとなるテンプレートと、テンプレートのテンプレートになるmyheader.gohtmlを作成しています。
|--main.go
|--templates
| |--index.gohtml
| |--myheader.gohtml
メインとなるテンプレートに{{template "myheader"}}と記述します。
index.gohtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documents</title>
</head>
<body>
<p>{{template "myheader"}}</p>
<h1>Hello, {{.}}!</h1>
</body>
</html>
そして、この{{template "myheader"}}に挿入する内容をmyheader.gohtmlファイルに{{define "myheader"}}{{end}}で囲って記述します。
myheader.gohtml
{{define "myheader"}}
これは<myheader>の記述です。
{{end}}
goファイルは次のようにします。
main.go
package main
import (
"log"
"os"
"text/template"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
}
func main() {
word := "golang"
nf, err := os.Create("index.html")
if err != nil {
log.Fatalln(err)
}
defer nf.Close()
err = tpl.ExecuteTemplate(nf, "index.gohtml", word)
if err != nil {
log.Fatalln(err)
}
}
main.goを実行すると2つのテンプレートが反映されたindex.htmlが作成されます。
テンプレートのテンプレートに値を渡せます
{{template "myheader" .}}として値を後続に渡すことができます。
index.gohtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Documents</title>
</head>
<body>
<h1>main.goから渡された変数: {{.}}</h1> <!-- main.goから渡された変数を表示 -->
<p>{{template "myheader" .}}</p> <!-- myheader.gohtmlに変数を渡す -->
</body>
</html>
myheader.gohtml
{{define "myheader"}}
これは<myheader>の記述です。<br>
index.gohtmlから渡された変数:{{.}}
{{end}}
main.go
package main
import (
"log"
"os"
"text/template"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*.gohtml"))
}
func main() {
word := "golang"
nf, err := os.Create("index.html")
if err != nil {
log.Fatalln(err)
}
err = tpl.ExecuteTemplate(nf, "index.gohtml", word)
if err != nil {
log.Fatalln(err)
}
}
出力されるindex.html
実践的な使い方
実際のサーバー運営をイメージすると、HTMLのヘッダーやフッターは決まり文句なので改修することはあまりなく本文とは切り離しておきたいですよね。これまでの総復習的な意味合いを込めて作成例を挙げておきます。
templates/header.gohtml
{{define "header"}}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{{.Title}}</title>
</head>
<body>
{{end}}
templates/footer.gohtml
{{define "footer"}}
<div>Copyright © hiroyuki ichijo</div>
</body>
</html>
{{end}}
手当をするメイン部分は次のように簡潔になります。
templates/tpl.gohtml
{{template "header" .}}
<h1>{{.Message}}</h1>
<h2>現在の時刻:{{.Time.Format "2006/1/2 15:04:05"}}</h2>
{{template "footer"}}
goのメインコードはこちら
main.go
package main
import (
"html/template"
"os"
"time"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*"))
}
func main() {
type source struct {
Title, Message string
Time time.Time
}
nf, _ := os.Create("index.html")
defer nf.Close()
var data source
data = source{
Title: "test page",
Message: "本日は晴天なり",
Time: time.Now(),
}
_ = tpl.ExecuteTemplate(nf, "tpl.gohtml", data)
}
実行結果は、
goコードとテンプレートの使い分けですが、goコードではデータの作成や計算部分を担当し、テンプレートで表示形式を整えるのが分かりやすいと思います。テンプレートでインナー定義関数を利用して計算や大小比較することは可能ですが、ごちゃごちゃしてしまうことがよくあります。役割分担をスパッと切り分けたほうが管理上も精神衛生的にも良いでしょう。