htmlのtemplate【Go】 - 技術向上で紹介した下記関数ですと、
同じtemplateであっても、処理毎に毎回templateの読み込みが行われてしまいます。
func renderTemplate(w http.ResponseWriter, templ string, p *Page) {
t, _ := template.ParseFiles(templ + ".html")
t.Execute(w, p)
}
templateをキャッシュして効率よく処理させる方法があります。
var templates = template.Must(template.ParseFiles("edit.html", "view.html")) // template情報をキャッシュ
func renderTemplate(w http.ResponseWriter, templ string, p *Page) {
err := templates.ExecuteTemplate(w, templ + ".html", p) // キャッシュされたtemplateから対象を呼び出し、pageの内容書き込みを実施する
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) // 500エラーを返す
}
}
template.ParseFiles()は可変長引数をとり、その引数としてキャッシュさせたいファイルの名前を指定します。
異なる階層の同じファイル名を複数指定した場合、最後に指定したファイルのみがキャッシュされます。
template.Must()は独自にエラーチェックを行うため、
errorを返り値には持たず、ハンドリングする必要がありません。
全体例です。
type Page struct {
Title string
Body []byte
}
var templates = template.Must(template.ParseFiles("edit.html", "view.html"))
func renderTemplate(w http.ResponseWriter, templ string, p *Page) {
err := templates.ExecuteTemplate(w, templ + ".html", p)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func load(title string) (*Page, error) {
filename := title + ".txt"
body, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return &Page{Title: title, Body: body}, nil
}
func viewHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[len("/view/"):]
p, err := load(title)
if err != nil {
http.Redirect(w, r, "/edit/"+title, http.StatusFound)
return
}
renderTemplate(w, "view", p)
}
func editHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[len("/edit/"):]
p, err := load(title)
if err != nil {
p = &Page{Title: title}
}
renderTemplate(w, "edit", p)
}
func main() {
http.HandleFunc("/view/", viewHandler)
http.HandleFunc("/edit/", editHandler)
log.Fatalln(http.ListenAndServe(":8080", nil))
}
template.ParseGlob()と合わせるパターンも多いかもしれません。
template.ParseGlob()【Go】 - 技術向上
階層
main.go
templates
blabla.gohtml
tpl1.gohtml
tpl2.gohtml
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*")) // templates以下の全ファイルを取り込み、キャッシュ
}
func main() {
nf, err := os.Create("index.html")
if err != nil {
log.Fatal(err)
}
err = tpl.ExecuteTemplate(nf, "tpl1.gohtml", nil) // tpl1.gohtmlの内容をindex.htmlにコピー
if err != nil {
log.Fatal(err)
}
err = tpl.ExecuteTemplate(os.Stdout, "tpl2.gohtml", nil) // tpl2.gohtmlの内容を画面出力
if err != nil {
log.Fatal(err)
}
}