技術向上

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

templateへのデータ渡し【Go】

templateへのデータ渡しを、goファイル上で指定する事ができます。

intやstring


階層が次のようになっているとします。

main.go
templates
    blabla.gohtml
    tpl1.gohtml
    tpl2.gohtml


main.goの内容です。

var tpl *template.Template

func init() {
    tpl = template.Must(template.ParseGlob("templates/*"))
}

func main() {
    nf, err := os.Create("index.html")
    if err != nil {
        log.Fatal(err)
    }

    err = tpl.ExecuteTemplate(nf, "tpl1.gohtml", 1)    // 1を渡す
    if err != nil {
        log.Fatal(err)
    }
}


tpl1.gohtmlの内容です。
変数に格納する事で、template内にて使いまわす事ができます。

{{$value := .}}    // $valueにgoファイルから渡される内容を格納
******
tpl1 {{$value}} on {{$value}}    // $valueを2度出力
******


上記条件でmain.goを実行すると、index.htmlの内容が次のようになります。

******
tpl1 1 on 1
******


slice

「intやstring」で紹介した内容から変更点のみを抜粋します。

main.goです。

func main() {
    ...

    s := []string{"a", "i", "u", "e", "o"}

    err = tpl.ExecuteTemplate(nf, "tpl1.gohtml", s)    // sを渡す
    if err != nil {
        log.Fatal(err)
    }
}


tpl1.gohtmlの内容です。
スライスなどの中身をループ処理をして取り出す際、
「{{range .}} {{end}}」を使用します。

<h1>tpl1</h1>

<ul>
{{range .}}    // ここの「.」は渡したスライスを意味する
    <li>{{.}}</li>    // ここの「.」はスライスの中からループで取り出した値を意味する
{{end}}
</ul>


上記条件でmain.goを実行すると、index.htmlの内容が次のようになります。

******
<h1>tpl1</h1>

<ul>

    <li>a</li>

    <li>i</li>

    <li>u</li>

    <li>e</li>

    <li>o</li>

</ul>
******

また、templateファイルを次のようにすれば、indexを出力することもできます。

<h1>tpl1</h1>

<ul>
{{range $index, $value := .}}    // スライスからindexとvalueを取得し、変数に格納
    <li>{{$index}}: {{$value}}</li>    // 変数をそれぞれ{{}}で囲んで出力する
{{end}}
</ul>


map

「intやstring」で紹介した内容から変更点のみを抜粋します。

main.goです。

func main() {
    ...

    m := map[string]int{
        "Milan":    1899,
        "Inter":    1908,
        "Juventus": 1897,
    }
    err = tpl.ExecuteTemplate(nf, "tpl1.gohtml", m)    // mを渡す
    if err != nil {
        log.Fatal(err)
    }
}


tpl1.gohtmlの内容です。
中身をループ処理で取り出す際、
「{{range .}} {{end}}」を使用します。
goファイルから渡されたデータを格納する際に、左辺を1つの変数のみ記載した場合は、
valueのみが変数に格納されます。

<h1>tpl1</h1>

<ul>
{{range $key, $value := .}}    // keyとvalue両方を変数に格納する
    <li>{{$key}}: {{$value}}</li>
{{end}}
</ul>


上記条件でmain.goを実行すると、index.htmlの内容が次のようになります。
mapの場合、keyの昇順で自動的にsortされます。

******
<h1>tpl1</h1>

<ul>

    <li>Inter: 1908</li>

    <li>Juventus: 1897</li>

    <li>Milan: 1899</li>

</ul>
******


struct

「intやstring」で紹介した内容から変更点のみを抜粋します。 3つのstructをスライスにして出力します。

main.goです。

type team struct {
    Name   string
    League string
}

func main() {
    ...

    milan := &team{
        Name:   "Milan",
        League: "SerieA",
    }

    liverpool := &team{
        Name:   "Liverpool FC",
        League: "Premire",
    }

    sevilla := &team{
        Name:   "Sevilla F.C.",
        League: "La Liga",
    }

    teams := []*team{milan, liverpool, sevilla}

    err = tpl.ExecuteTemplate(nf, "tpl1.gohtml", teams)
    if err != nil {
        log.Fatal(err)
    }
}


tpl1.gohtmlの内容です。
スライスなどの中身をループ処理で取り出す際、
「{{range .}} {{end}}」を使用します。
structの場合はフィールド名が定義されていますので、「.<フィールド名>」で出力する事ができます。

<h1>tpl1</h1>

<ul>
{{range .}}
    <li>{{.Name}} : {{.League}}</li>
{{end}}
</ul>


上記条件でmain.goを実行すると、index.htmlの内容が次のようになります。

******
<h1>tpl1</h1>

<ul>

    <li>Milan : SerieA</li>

    <li>Liverpool FC : Premire</li>

    <li>Sevilla F.C. : La Liga</li>

</ul>
******


スライスではなく単体のstructを渡したい場合には、
templateの「{{range .}} {{end}}」を取り除いて、
goファイルのtemplate.ExecuteTemplate()で渡すデータをstructに変更します。

sliceをフィールドにもつstruct

slice型をフィールドにもつstructは複雑な形式ではありますが、
このようなことも出来るということで、紹介します。

「intやstring」で紹介した内容から変更点のみを抜粋します。

main.goです。

type team struct {
    Name   string
    League string
}

type player struct {
    Name string
    Team string
}

func main() {
    ...

    milan := &team{
        Name:   "Milan",
        League: "SerieA",
    }

    liverpool := &team{
        Name:   "Liverpool FC",
        League: "Premire",
    }

    sevilla := &team{
        Name:   "Sevilla F.C.",
        League: "La Liga",
    }

    ronaldo := &player{
        Name: "Ronaldo",
        Team: "Juventus",
    }

    messi := &player{
        Name: "Messi",
        Team: "Barcelona",
    }

    teams := []*team{milan, liverpool, sevilla}
    players := []*player{ronaldo, messi}

    err = tpl.ExecuteTemplate(nf, "tpl1.gohtml", struct {    // {}{}で、定義、代入を連続して行うことも可能
        Teams   []*team
        Players []*player
    }{
        teams,
        players,
    })
    if err != nil {
        log.Fatal(err)
    }
}


tpl1.gohtmlの内容です。
スライスなどの中身をループ処理で取り出す際、
「{{range .}} {{end}}」を使用します。
structの場合はフィールド名が定義されていますので、「.<フィールド名>」で出力する事ができます。
rangeに渡す際に、どのフィールドかを「.<フィールド名>」で指定することによって、
ループ処理で取り出す対象を指定する事ができます。

<h1>tpl1</h1>

<ul>
{{range .Teams}}    // Teamsをループ処理
    <li>{{.Name}} : {{.League}}</li>
{{end}}
</ul>

<ol>
{{range .Players}}    // Playersをループ処理
    <li>{{.Name}} : {{.Team}}</li>
{{end}}
</ol>


上記条件でmain.goを実行すると、index.htmlの内容が次のようになります。

******
<h1>tpl1</h1>

<ul>

    <li>Milan : SerieA</li>

    <li>Liverpool FC : Premire</li>

    <li>Sevilla F.C. : La Liga</li>

</ul>

<ol>

    <li>Ronaldo : Juventus</li>

    <li>Messi : Barcelona</li>

</ol>
******


template.ParseFiles()【Go】 - 技術向上

template.ParseGlob()【Go】 - 技術向上