要处理Web应用程序中的每个请求,有关模板的常规代码如下:
t:= template.New("welcome")
t, _ = t.ParseFiles("welcome.tpl")
t.Execute(w, data)
我猜ParseFiles
每次花费很多。是否可以重用模板?所以我改进了它:
//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)
我想通过将模板放入地图或缓存来提高效率是可行还是可行的?
我也想知道函数Execute
是否是线程安全的?
func (t *Template) Execute(wr io.Writer, data interface{}) (err error)
答案 0 :(得分:13)
模板实际上可以作为模板的映射。这是我的所作所为:
我声明了一个全局模板变量:
var t = template.New("master")
我实际上并没有使用“主”模板,除了作为其他模板的容器。
然后,我在应用启动时加载所有模板:
func init() {
_, err := t.ParseGlob("templates/*.html")
if err != nil {
log.Fatalln("Error loading templates:", err)
}
}
然后,当我想使用其中一个模板时,我会按名称提出要求:
t.ExecuteTemplate(w, "user.html", data)
答案 1 :(得分:0)
从template.go的源代码中,Execute函数使用Lock,我是新手,它看起来是线程安全的,但如果将模板实例放到地图上并尝试重用它可能效率不高,如果您需要提供大量并发请求:
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)
}
答案 2 :(得分:0)
如果模板与处理程序有一对一的关系,另一种方法是使用闭包。好处是模板只执行一次,不需要全局变量,但缺点是模板只能在声明它的处理程序中使用。
func templateHandler() http.HandlerFunc {
// template is executed once
tmp := template.Must(template.ParseFiles("welcome.html"))
// return our handler with the template available through the closure
return func(w http.ResponseWriter, r *http.Request) {
// ...perform other handler work ...
// execute template against data
tmp.Execute(w, myData)
}
}
func main() {
http.HandleFunc("/gopher", templateHandler())
http.ListenAndServe(":8080", nil)
}