Go言語によるWebサーバー作成入門 ーテンプレートー2

公開:2020/10/21
更新:2020/10/21
7 min読了の目安(約6300字TECH技術記事

(作成2020.10.21)
前回の記事はこちら

テンプレートに値を渡す

まずテンプレートの方に値を渡す場所を{{.}}で指定します。

tpl.gohtml
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <h1>Hello, {{.}}!</h1>
</body>
</html>

tpl.ExecuteTemplateの第3引数に渡す値を入れます。(これまでずっとnilにしてましたが、疑問に思って方、えらい!)

main.go
package main

import (
	"log"
	"os"
	"text/template"
)

var tpl *template.Template

func init() {
	tpl = template.Must(template.ParseFiles("tpl.gohtml"))
}

func main() {
	str := "golang web"

	nf, err := os.Create("index.html")
	if err != nil {
		log.Fatalln("error creating file", err)
	}
	defer nf.Close()

	err = tpl.ExecuteTemplate(nf, "tpl.gohtml", str)
	if err != nil {
		log.Fatalln(err)
	}
}

アウトプットされるindex.htmlはこうなります。

テンプレートの中では、以下のように変数名を付けることもできます。アウトプット結果は同じです。

tpl.gohtml
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    {{$dog := .}}
    <h1>Hello, {{$dog}}!</h1>
</body>
</html>

sliceも渡せます

main.go
package main

import (
	"log"
	"os"
	"text/template"
)

var tpl *template.Template

func init() {
	tpl = template.Must(template.ParseFiles("tpl.gohtml"))
}

func main() {
	dogs := []string{"Alaskan Malamute", "Akita", "Chouchou", "Samoyed"}

	nf, err := os.Create("index.html")
	if err != nil {
		log.Fatalln("error creating file", err)
	}
	defer nf.Close()

	err = tpl.ExecuteTemplate(nf, "tpl.gohtml", dogs)
	if err != nil {
		log.Fatalln(err)
	}
}

テンプレートでは、{{range .}}と{{end}}ではさみます。

tpl.gohtml
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Peeps</title>
</head>
<body>
<ul>
    {{range .}}
    <li>{{.}}</li>
    {{end}}
</ul>
</body>
</html>

結果はこちら

rangeなので番号も出力できます

tpl.gohtml

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Peeps</title>
</head>
<body>
<ul>
    {{range $index, $dog := .}}
    <li>{{$index}} - {{$dog}}</li>
    {{end}}
</ul>
</body>
</html>

出力結果は、

mapもできます

tpl.gohtml
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Peeps</title>
</head>
<body>
<ul>
    {{range $index, $dog := .}}
    <li>{{$index}} - {{$dog}}</li>
    {{end}}
</ul>
</body>
</html>
main.go
package main

import (
	"log"
	"os"
	"text/template"
)

var tpl *template.Template

func init() {
	tpl = template.Must(template.ParseFiles("tpl.gohtml"))
}

func main() {
	dogs := map[string]string{
		"Samoyed":          "Russia",
		"Alaskan Malamute": "Alaska",
		"Akita":            "Japan",
		"Chouchou":         "China",
	}

	nf, err := os.Create("index.html")
	if err != nil {
		log.Fatalln("error creating file", err)
	}
	defer nf.Close()

	err = tpl.ExecuteTemplate(nf, "tpl.gohtml", dogs)
	if err != nil {
		log.Fatalln(err)
	}
}

出力結果は、

順番はmapに入っている順番にならないことに注意してください。

structもいけます

渡す変数をグローバル(つまり頭文字を大文字)にしなければなりません。

main.go
package main

import (
	"log"
	"os"
	"text/template"
)

var tpl *template.Template

type dog struct {
	Kind    string
	Country string
}

func init() {
	tpl = template.Must(template.ParseFiles("tpl.gohtml"))
}

func main() {

	cute := dog{
		Kind:    "Samoyed",
		Country: "Russia",
	}

	nf, err := os.Create("index.html")
	if err != nil {
		log.Fatalln("error creating file", err)
	}
	defer nf.Close()

	err = tpl.ExecuteTemplate(nf, "tpl.gohtml", cute)
	if err != nil {
		log.Fatalln(err)
	}
}
tpl.gohtml

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Peeps</title>
</head>
<body>
<ul>
    <li>{{.Kind}} - {{.Country}}</li>
</ul>
</body>
</html>

slice struct

main.go
package main

import (
	"log"
	"os"
	"text/template"
)

var tpl *template.Template

type dog struct {
	Kind    string
	Country string
}

func init() {
	tpl = template.Must(template.ParseFiles("tpl.gohtml"))
}

func main() {

	cute := dog{
		Kind:    "Samoyed",
		Country: "Russia",
	}
	cute2 := dog{
		Kind:    "Akita",
		Country: "Japan",
	}

	dogs := []dog{cute, cute2}

	nf, err := os.Create("index.html")
	if err != nil {
		log.Fatalln("error creating file", err)
	}
	defer nf.Close()

	err = tpl.ExecuteTemplate(nf, "tpl.gohtml", dogs)
	if err != nil {
		log.Fatalln(err)
	}
}
tpl.gohtml

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Peeps</title>
</head>
<body>
<ul>
    {{range .}}
    <li>{{.Kind}} - {{.Country}}</li>
    {{end}}
</ul>
</body>
</html>

struct slice structもいけます

・・・同じような感じでいけます、と省略しようかと思ったけど書きました。

main.go
package main

import (
	"log"
	"os"
	"text/template"
)

var tpl *template.Template

type dog struct {
	Kind    string
	Country string
}

type vegetable struct {
	Name  string
	Color string
}

func init() {
	tpl = template.Must(template.ParseFiles("tpl.gohtml"))
}

func main() {

	cute := dog{
		Kind:    "Samoyed",
		Country: "Russia",
	}
	cute2 := dog{
		Kind:    "Akita",
		Country: "Japan",
	}

	v1 := vegetable{
		Name:  "onion",
		Color: "white",
	}
	v2 := vegetable{
		Name:  "carrot",
		Color: "orange",
	}
	dogs := []dog{cute, cute2}
	vegetables := []vegetable{v1, v2}

	data := struct {
		AAA []dog
		BBB []vegetable
	}{
		dogs,
		vegetables,
	}

	nf, err := os.Create("index.html")
	if err != nil {
		log.Fatalln("error creating file", err)
	}
	defer nf.Close()

	err = tpl.ExecuteTemplate(nf, "tpl.gohtml", data)
	if err != nil {
		log.Fatalln(err)
	}
}
tpl.gohtml

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Peeps</title>
</head>
<body>
    <ul>
        {{range .AAA}}
        <li>{{.Kind}} - {{.Country}}</li>
        {{end}}
    </ul>
    <ul>
        {{range .BBB}}
        <li>{{.Name}} - {{.Color}}</li>
        {{end}}
    </ul>
    </body>
</html>