templateファイルの中で、goファイル上で記述したメソッドを使用することができます。
メソッドを定義していないtypeに対して使おうとすると、エラーが発生します。
引数あり
main.goです。
var tpl *template.Template
type Team struct {
Name string
Est int
}
type League struct {
Name string
Teams []*Team
}
type NPB struct {
Pacific, Central *League
}
func (t *Team) Years(y int) int { // Teamのポインタレシーバーを登録
return time.Now().Year() - y // 創設からの年数を返す
}
func init() {
tpl = template.Must(template.ParseFiles("tpl.gohtml"))
}
func main() {
nf, err := os.Create("index.html")
if err != nil {
log.Fatal(err)
}
npb := &NPB{
Pacific: &League{
Name: "Pacific League",
Teams: []*Team{
&Team{Name: "Lions", Est: 1950},
&Team{Name: "Hawks", Est: 1938},
&Team{Name: "Fighters", Est: 1946},
&Team{Name: "Buffaloes", Est: 1936},
&Team{Name: "Marines", Est: 1950},
&Team{Name: "Eagles", Est: 2005},
},
},
Central: &League{
Name: "Central League",
Teams: []*Team{
&Team{Name: "Carp", Est: 1950},
&Team{Name: "Swallows", Est: 1950},
&Team{Name: "Giants", Est: 1934},
&Team{Name: "BayStars", Est: 1950},
&Team{Name: "Dragons", Est: 1936},
&Team{Name: "Tigers", Est: 1935},
},
},
}
err = tpl.ExecuteTemplate(nf, "tpl.gohtml", npb)
if err != nil {
log.Fatalln(err)
}
}
tpl.gohtmlです。
一番端のパイプラインを挟んだ対象が、メソッドの引数として扱われます。
(複数のパイプラインを記述することができるため、この表現を使いました。)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
{{.Pacific.Name}}:
{{range .Pacific.Teams}}
<li>{{.Name}}, established {{.Est | .Years}} years before.</li> // Team.Estに対してYearsを適用。Yearsの引数がTeam.Estにあたる
{{end}}
{{.Central.Name}}:
{{range .Central.Teams}}
<li>{{.Name}}, established {{.Est | .Years}} years before.</li>
{{end}}
</body>
</html>
実行すると、index.htmlは次のようになります。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
Pacific League:
<li>Lions, established 68 years before.</li>
<li>Hawks, established 80 years before.</li>
<li>Fighters, established 72 years before.</li>
<li>Buffaloes, established 82 years before.</li>
<li>Marines, established 68 years before.</li>
<li>Eagles, established 13 years before.</li>
Central League:
<li>Carp, established 68 years before.</li>
<li>Swallows, established 68 years before.</li>
<li>Giants, established 84 years before.</li>
<li>BayStars, established 68 years before.</li>
<li>Dragons, established 82 years before.</li>
<li>Tigers, established 83 years before.</li>
</body>
</html>
※空行を削除しています。
上記の例ですと、tpl.gohtmlで例えば「{{.Pacific.Name | .Years}}:」としてしまうと、
*main.NPBにはYearsが登録されていない旨を示すエラーになります。
引数なし
次は、引数を取らないメソッドの例です。 先述の例との差分のみ記述します。
main.goです。 Teamに対して、Star()メソッドを追加しています。
func (t *Team) Star() string {
return "★★★ " + t.Name + " ★★★"
}
tpl.gohtmlです。
indexが0のTeamについて、Name出力にStar()メソッドを使うようにしました。
<body>
{{.Pacific.Name}}:
{{range $i, $v := .Pacific.Teams}}
<li>{{if eq $i 0}}{{.Star}}{{else}}{{.Name}}{{end}}, established {{.Est | .Years}} years before.</li>
{{end}}
{{.Central.Name}}:
{{range $i, $v := .Central.Teams}}
<li>{{if eq $i 0}}{{.Star}}{{else}}{{.Name}}{{end}}, established {{.Est | .Years}} years before.</li>
{{end}}
</body>
index.htmlは次のようになります。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
Pacific League:
<li>★★★ Lions ★★★, established 68 years before.</li>
<li>Hawks, established 80 years before.</li>
<li>Fighters, established 72 years before.</li>
<li>Buffaloes, established 82 years before.</li>
<li>Marines, established 68 years before.</li>
<li>Eagles, established 13 years before.</li>
Central League:
<li>★★★ Carp ★★★, established 68 years before.</li>
<li>Swallows, established 68 years before.</li>
<li>Giants, established 84 years before.</li>
<li>BayStars, established 68 years before.</li>
<li>Dragons, established 82 years before.</li>
<li>Tigers, established 83 years before.</li>
</body>
</html>
※空行を削除しています。