templateキャッシュ【Go】
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) } }