技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

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>

※空行を削除しています。