是否有必要将模板放入地图以便在Go中重复使用?

时间:2013-03-12 02:14:29

标签: go

要处理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)

3 个答案:

答案 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)
}