Golang多模板缓存

huangapple go评论75阅读模式
英文:

Golang Multi templates caching

问题

我是你的中文翻译助手,以下是翻译好的内容:

我对Golang世界还很陌生,我正在尝试使用模板文件和良好的缓存系统设置一个Web项目。

我有layout.html1.html2.html这三个文件。

所以在我的渲染函数中加载layout.html

err := templates.ExecuteTemplate(w, "layout.html", nil)

layout.html的内容如下:

...
<body>{{template "content" .}}</body>
...

1.html的内容如下:

{{define "content"}}这是第一页。{{end}}

2.html的内容如下:

{{define "content"}}这是第二页。{{end}}

我不能使用以下代码:

var templates = template.Must(template.ParseFiles(
	"layout.html",
	"1.html",
	"2.html"))

因为2.html会覆盖1.html

所以我有两种方法:

  1. 在每个处理函数中定义ParseFiles(每次渲染页面时都要执行),性能很差。
  2. init函数中定义一个模板数组,类似这样(示例):
templates["1"] = template.Must(template.ParseFiles("layout.html","1.html"))
templates["2"] = template.Must(template.ParseFiles("layout.html","2.html"))

是否有任何新的或更好的方法来解决这个问题?

英文:

I'm new to the world of Golang and I'm trying to set up a web project with templates files and good caching system.

I have layout.html, 1.html, 2.html.

So I load layout.html in my render function :

err := templates.ExecuteTemplate(w, &quot;layout.html&quot;, nil)

layout.html look like this :

...   
&lt;body&gt;{{template &quot;content&quot; .}}&lt;/body&gt;
...

1.html

{{define &quot;content&quot;}}This is the first page.{{end}}

2.html

{{define &quot;content&quot;}}This is the second page.{{end}}

I can't use

var templates = template.Must(template.ParseFiles(
	&quot;layout.html&quot;,
	&quot;1.html&quot;,
	&quot;2.html&quot;))

Because 2.html override 1.html.

So I have two ways :

  1. Define ParseFiles in each handler function. (every time a page is rendered) Very bad perf
  2. Define an array of template like this in the init function (example):
    templates[&quot;1&quot;] = template.Must(template.ParseFiles(&quot;layout.html&quot;,&quot;1.html&quot;))
    templates[&quot;2&quot;] = template.Must(template.ParseFiles(&quot;layout.html&quot;,&quot;2.html&quot;))

Is there any new way or better way to do this ?

答案1

得分: 3

包级别的映射或变量都是缓存编译模板的好方法。上面的第2个代码是可以的。以下是如何使用包级别变量:

var t1 = template.Must(template.ParseFiles("layout.html","1.html"))
var t2 = template.Must(template.ParseFiles("layout.html","2.html"))

像这样使用变量:

err := t1.Execute(w, data)

问题中的代码和上面这个答案中的代码都会两次加载"layout.html"。可以避免这种情况:

var layout = template.Must(template.ParseFiles("layout.html"))
var t1 = template.Must(layout.Clone().ParseFiles("1.html"))
var t2 = template.Must(layout.Clone().ParseFiles("2.html"))
英文:

Package-level maps or variables are both a good way to cache compiled templates. Code in #2 above is OK. Here's how to use package-level variables:

var t1 = template.Must(template.ParseFiles(&quot;layout.html&quot;,&quot;1.html&quot;))
var t2 = template.Must(template.ParseFiles(&quot;layout.html&quot;,&quot;2.html&quot;))

Use the variables like this:

err := t1.Execute(w, data)

The code in the question and this code above in this answer load "layout.html" twice. This can be avoided:

var layout = template.Must(template.ParseFiles(&quot;layout.html&quot;))
var t1 = template.Must(layout.Clone().ParseFiles(&quot;1.html&quot;))
var t2 = template.Must(layout.Clone().ParseFiles(&quot;2.html&quot;))

答案2

得分: 2

在我的项目中,我使用这个辅助函数:

func executeTemplate(tmpls *template.Template, tmplName string, w io.Writer, data interface{}) error {
    var err error
    layout := tmpls.Lookup("layout.html")
    if layout == nil {
        return errNoLayout
    }

    layout, err = layout.Clone()
    if err != nil {
        return err
    }

    t := tmpls.Lookup(tmplName)
    if t == nil {
        return errNoTemplate
    }

    _, err = layout.AddParseTree("content", t.Tree)
    if err != nil {
        return err
    }

    return layout.Execute(w, data)
}

tmpls 是包含所有解析模板的模板,例如来自 ParseFiles 的“子模板”。layout.html 大致如下:

<main class="container">
{{template "content" .}}
</main>

而其他模板则是这样的:

<h1>Welcome</h1>

注意,内容模板不需要以 {{define "content"}} 开头。

英文:

In my projects I use this helper function:

func executeTemplate(tmpls *template.Template, tmplName string, w io.Writer, data interface{}) error {
	var err error
	layout := tmpls.Lookup(&quot;layout.html&quot;)
	if layout == nil {
		return errNoLayout
	}

	layout, err = layout.Clone()
	if err != nil {
		return err
	}

	t := tmpls.Lookup(tmplName)
	if t == nil {
		return errNoTemplate
	}

	_, err = layout.AddParseTree(&quot;content&quot;, t.Tree)
	if err != nil {
		return err
	}

	return layout.Execute(w, data)
}

tmpls is the template which contains all parsed templates as "sub-templates", e.g. from ParseFiles. layout.html looks something like this:

&lt;main class=&quot;container&quot;&gt;
{{template &quot;content&quot; .}}
&lt;/main&gt;

While other templates are like this:

&lt;h1&gt;Welcome&lt;/h1&gt;

Notice, content templates don't need to start with {{define &quot;content&quot;}}.

huangapple
  • 本文由 发表于 2017年8月23日 06:52:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/45828142.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定