英文:
Golang Multi templates caching
问题
我是你的中文翻译助手,以下是翻译好的内容:
我对Golang世界还很陌生,我正在尝试使用模板文件和良好的缓存系统设置一个Web项目。
我有layout.html
、1.html
和2.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
。
所以我有两种方法:
- 在每个处理函数中定义
ParseFiles
(每次渲染页面时都要执行),性能很差。 - 在
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, "layout.html", nil)
layout.html
look like this :
...
<body>{{template "content" .}}</body>
...
1.html
{{define "content"}}This is the first page.{{end}}
2.html
{{define "content"}}This is the second page.{{end}}
I can't use
var templates = template.Must(template.ParseFiles(
"layout.html",
"1.html",
"2.html"))
Because 2.html
override 1.html
.
So I have two ways :
- Define ParseFiles in each handler function. (every time a page is rendered) Very bad perf
- Define an array of template like this in the init function (example):
templates["1"] = template.Must(template.ParseFiles("layout.html","1.html"))
templates["2"] = template.Must(template.ParseFiles("layout.html","2.html"))
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("layout.html","1.html"))
var t2 = template.Must(template.ParseFiles("layout.html","2.html"))
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("layout.html"))
var t1 = template.Must(layout.Clone().ParseFiles("1.html"))
var t2 = template.Must(layout.Clone().ParseFiles("2.html"))
答案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("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
is the template which contains all parsed templates as "sub-templates", e.g. from ParseFiles
. layout.html
looks something like this:
<main class="container">
{{template "content" .}}
</main>
While other templates are like this:
<h1>Welcome</h1>
Notice, content templates don't need to start with {{define "content"}}
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论