templateに渡したdataに対してメソッドを使用する【Go】
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>
※空行を削除しています。