To deal with every request in a web application, the normal code about templates is like this:
t:= template.New("welcome")
t, _ = t.ParseFiles("welcome.tpl")
t.Execute(w, data)
I guess ParseFiles
every time cost a lot. Is it possible to reuse the template? So I improved it like this:
//templateMap := make(map[string][template])
//...
tplName :="welcome"
t := templateMap[tplName]
if t=nil{
t:= template.New(tplName )
t, _ = t.ParseFiles("welcome.tpl")
templateMap[tplName] = t
}
t.Execute(w, data)
I wonder it is feasible or practicable to improve efficiency by putting templates into a map or a cache? I also wonder the function Execute
is thread safe or not?
func (t *Template) Execute(wr io.Writer, data interface{}) (err error)
A template can actually act as a map of templates by itself. Here's what I do:
I declare a global template variable:
var t = template.New("master")
I don't actually use the "master" template, except as a container for other templates.
Then, I load all the templates when my app starts:
func init() {
_, err := t.ParseGlob("templates/*.html")
if err != nil {
log.Fatalln("Error loading templates:", err)
}
}
Then when I want to use one of the templates, I ask for it by name:
t.ExecuteTemplate(w, "user.html", data)
From the source code of template.go, the Execute function use a Lock, I'm a newbie, it looks is thread safe, but might not efficiency if put the template instance to a map and try to reuse it, if you need to serve lots of concurrent requests:
func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
t.nameSpace.mu.Lock()
if !t.escaped {
if err = escapeTemplates(t, t.Name()); err != nil {
t.escaped = true
}
}
t.nameSpace.mu.Unlock()
if err != nil {
return
}
return t.text.Execute(wr, data)
}