预缓存Golang模板或更有效的方法

时间:2019-01-25 16:28:43

标签: go go-templates

我有一个Web应用程序,我正在尝试按照以下建议预先缓存我的模板: https://golang.org/doc/articles/wiki/#tmp_10

目前这就是我正在做的。 (我提供了示例模板帮助器功能,以使您有所了解) (请注意,App对象是应用程序的其余部分,用于处理实际的Web服务和数据库内容)

///a function that the template can pass a different arg
func functiontakingarguments(arg1 string, arg2 string) (firststring string) {
    return arg1

}

func (app *App) defaultTemplHelpers(w http.ResponseWriter, r *http.Request) template.FuncMap {
    m := template.FuncMap{
        "sessionfoo": func() bool {
            //some function
            return hasUserSession(r)
        },
        "bar": functiontakingarguments,
    }
    /*
        Many many more template functions
    */
    return m
}

func myPageWithLayout(app *App, w http.ResponseWriter, r *http.Request, path string, file string, layout string, funcs template.FuncMap, data map[string]interface{}) {
    logger.Debugf("rendering template with layout %+v at path %+v, page %+v", layout, path, file)

    t, err := template.New(file).Funcs(funcs).ParseFiles(
        filepath.Join(templatesPath, path, file),
        filepath.Join(templatesPath, "layouts", layout),
    )

    if err != nil {
        logger.Errorf("error rendering html template %+v: %+v", file, err.Error())
        http.Error(w, "error", http.StatusInternalServerError)
        return
    }

    //previously used to establish default template data
    templData := map[string]interface{}{}
    // merge passed in data with our template data
    for k, v := range data {
        templData[k] = v
    }

    executeTemplate(w, t, templData)
}
///the following is an example of a template:

/*

apagewithfuncs.html:

<h1> Hello! </h1>
{{ functiontakingarguments "astring" "asecondstring" }}

{{ if sessionfoo }} Something to do with that session function {{else}} nevermind! {{end}}

*/

我敢打赌,您可以在这里轻松发现第一组问题。每次必须为每个请求从磁盘读取模板。

因为我有一些模板函数依赖于用户查看它们的内容或会话变量,所以我将r * http.Request传递给模板呈现函数,以便在调用我的辅助函数时,它们可以访问该请求数据。

据我所知,这意味着我无法按照先前的链接(https://golang.org/doc/articles/wiki/#tmp_10)中所述完全预缓存这些模板

因此,首先,这通常是一种不好的方法吗? (不是为了赚钱,而是其中一些代码来自另一个程序员)

第二,有没有办法使它更有效?例如,缓存其中的一部分但仍然能够使用那些辅助函数? 我很确定这整个设置会拖累我的应用程序性能,但我可能是错的。我试过一些丑陋的技巧,例如尝试(someargs ... interface {}),然后进行类型转换(是的,我是一个可怕的罪人)

1 个答案:

答案 0 :(得分:1)

将所有每个请求状态作为参数传递给Execute。 定义一个封装每个请求状态的类型:

im2, contours, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 

在模板中使用该类型:

simplevar := $(varname)
val = $($(simplevar)-value)

有了这些更改,可以在程序启动时对模板进行一次解析。假设模板指针存储在包级变量type data struct { r *http.Request Data map[string]interface{} } func (d *data) SessionFoo() bool { return hasUserSession(d.r) } 中,您可以像这样执行它:

<h1> Hello! </h1>
{{ functiontakingarguments "astring" "asecondstring" }}

{{ if $.SessionFoo }} Something to do with that session function {{else}} nevermind! {{end}}

templData["x"] is {{$.Data.x}}