m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

golangでtemplate(html)の確認

ページを表示する際はテンプレートを使用する

標準では"text/template"と"html/template"が存在する
※他にもあるかもしれないけどあとでやる

シンプルなテンプレート

構造
$ tree
.
├── main.go
└── templates
    └── index.tpl

$
templates/index.tpl
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>golang template test</title>
</head>
<body>
    <h1>Golang Template Sample</h1>
    <p>Title --[{{.Title}}]</p>
    <p>Message--[{{.Message}}] </p>
    <div>
        <h3>Items</h3>
        {{range .List}}
        <p>{{.}}</p>
        {{end}}
    </div>
    <div>
        Link: {{.Link}}
    </div>
</body>
</html>

※テンプレートは中括弧("{}")で挟むようです

main.go
package main

import (
	"fmt"
	"net/http"
	"html/template"
	"time"
)

func main(){
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

		fmt.Println(time.Now().Format("2006/01/02 15:04:05") + " " + r.URL.Path)

		// テンプレート用のファイルを読み込む
		tpl, err1 := template.ParseFiles("templates/index.tpl")
		if err1 != nil {
			panic(err1)
		}

		// テンプレートを出力
		err2 := tpl.Execute(w, struct {
			Title string
			Message string
			List []string
			Link string
		}{
			Title: "Hello",
			Message: "World",
			List: []string{
				"Item1",
				"Item2",
				"Item3",
			},
			Link: "<a href=\"/\">hoge</a>",
		})
		if err2 != nil {
			panic(err2)
		}

	})
	http.ListenAndServe(":9001", nil)
}
ページをひらくとこうなる

f:id:m_shige1979:20160126223113p:plain

一部のデータを加工する

templates/index.tpl
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>golang template test</title>
</head>
<body>
	<h1>Golang Template Sample</h1>
	<p>Title --[{{.Title}}]</p>
	<p>Message--[{{.Message}}] </p>
	<div>
		<h3>Items</h3>
		{{range .List}}
		<p>{{.}}</p>
		{{end}}
	</div>
	<div>
		Link: {{.Link | safe}}
	</div>
	<div>
        Link: {{.Link | lock}}
    </div>
</body>
</html>
main.go
package main

import (
	"fmt"
	"net/http"
	"html/template"
	"time"
)

func main(){
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

		fmt.Println(time.Now().Format("2006/01/02 15:04:05") + " " + r.URL.Path)

		// 独自関数でエスケープを解除
		funcMap := template.FuncMap{
			"safe": func(text string) template.HTML { return template.HTML(text) },
			"lock": func(text string) string { return "@@[" + text + "]@@" },
		}

		// テンプレート用のファイルを読み込む
		tpl, _:= template.New("index.tpl").Funcs(funcMap).ParseFiles("templates/index.tpl")

		// テンプレートを出力
		err2 := tpl.Execute(w, struct {
			Title string
			Message string
			List []string
			Link string
		}{
			Title: "Hello",
			Message: "World",
			List: []string{
				"Item1",
				"Item2",
				"Item3",
			},
			Link: "<a href=\"/\">hoge</a>",
		})
		if err2 != nil {
			panic(err2)
		}

	})
	http.ListenAndServe(":9001", nil)
}
結果

f:id:m_shige1979:20160126225319p:plain

複数のテンプレートをファイルを使用する

構成
.
├── main.go
└── templates
    ├── base.tpl
    └── contents.tpl
templates/base.tpl
{{ define "base" }}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>golang template test</title>
</head>
<body>
    <h1>Golang Template Sample</h1>
    <p>Title --[{{.Title}}]</p>
    <p>Message--[{{.Message}}] </p>
    <div>
        {{ template "contents" . }}
    </div>
</body>
</html>
{{ end }}
templates/contents.tpl
{{ define "contents" }}
    <div>
        <h3>Items</h3>
        {{range .List}}
        <p>{{.}}</p>
        {{end}}
    </div>
    <div>
        Link: {{.Link | safe}}
    </div>
    <div>
        Link: {{.Link | lock}}
    </div>
{{ end }}
main.go
package main

import (
	"fmt"
	"net/http"
	"html/template"
	"time"
)

func main(){
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {

		fmt.Println(time.Now().Format("2006/01/02 15:04:05") + " " + r.URL.Path)

		// 独自関数でエスケープを解除
		funcMap := template.FuncMap{
			"safe": func(text string) template.HTML { return template.HTML(text) },
			"lock": func(text string) string { return "@@[" + text + "]@@" },
		}

		// テンプレート用のファイルを読み込む
		tpl := template.Must(template.New("hoge").Funcs(funcMap).ParseFiles("templates/base.tpl", "templates/contents.tpl"))

		// テンプレートを出力
		err2 := tpl.ExecuteTemplate(w, "base", struct {
			Title string
			Message string
			List []string
			Link string
		}{
			Title: "Hello",
			Message: "World",
			List: []string{
				"Item1",
				"Item2",
				"Item3",
			},
			Link: "<a href=\"/\">hoge</a>",
		})
		if err2 != nil {
			panic(err2)
		}

	})
	http.ListenAndServe(":9001", nil)
}

頭パンクしそう(´・ω・`)

所感

やり方自体はパターンがあるからそのうち理解出来ていくと思うけどgo言語の書き方に慣れていないことや日本語のマニュアルがないのかエラーの意味をうまく理解できていないことがある。
いろいろ参考になりそうなソースがネットで検索したら出てくるので参考にしながらやっていくしかない