英文:
The Go Template ParseFiles func parsing multiple files
问题
如果将两个或多个文件传递给Go模板的ParseFiles函数,会发生什么情况?
ParseFiles函数的作用是:
ParseFiles解析指定的文件,并将生成的模板与t关联。如果发生错误,解析将停止,并且返回的模板为nil;否则返回t。至少必须有一个文件。由于ParseFiles创建的模板是由参数文件的基本名称命名的,因此t通常应该具有文件(基本)名称之一的名称。如果不是这样,根据调用ParseFiles之前t的内容,t.Execute可能会失败。在这种情况下,请使用t.ExecuteTemplate来执行有效的模板。
当解析具有相同名称但位于不同目录中的多个文件时,最后一个被提及的文件将是结果。
但我仍然不确定会对输出产生什么影响,对于:
MyTempl.ParseFiles(tf1)
与
MyTempl.ParseFiles(tf1, tf2)
tf2
的内容是否会附加到tf1
的内容中?
英文:
What would it happen if I pass two or more files to Go Template's ParseFiles func?
func (*Template) ParseFiles
It helps says:
> ParseFiles parses the named files and associates the resulting templates with t. If an error occurs, parsing stops and the returned template is nil; otherwise it is t. There must be at least one file. Since the templates created by ParseFiles are named by the base names of the argument files, t should usually have the name of one of the (base) names of the files. If it does not, depending on t's contents before calling ParseFiles, t.Execute may fail. In that case use t.ExecuteTemplate to execute a valid template.
>
> When parsing multiple files with the same name in different directories, the last one mentioned will be the one that results.
But I'm still not sure what would the differences be that affects the output, for
MyTempl.ParseFiles(tf1)
vs.
MyTempl.ParseFiles(tf1, tf2)
Will the content of tf2
be appended to that of tf1
?
答案1
得分: 9
首先,让我们简单介绍一下"template"的概念:
template.Template
是_“解析模板的表示”_。但是这里的措辞有点不够准确。template.Template
值可以是(通常是)多个相关模板的集合。template.Template
有一个未导出的字段:
tmpl map[string]*Template // 从名称到已定义模板的映射。
这个 tmpl
字段保存了所有其他相关模板,这些模板对模板可见,并且可以通过它们的名称进行引用。
你可以在这个回答中了解更多信息:https://stackoverflow.com/questions/41176355/go-template-name/41187671#41187671
回到 Template.ParseFiles()
方法。这个方法从传递给它的文件中解析多个模板。从文件中解析的模板将以文件名命名(不包括文件夹,只有文件名),并且它们将被添加到方法接收者指定的 t
模板的内部关联模板映射中。
解析的模板不会被追加。将为它们创建多个独立的 template.Template
值,但它们将被关联起来(因此它们可以相互引用,例如它们可以相互包含)。
让我们看一个例子。假设我们有以下两个模板文件:
a.html
的内容是:
我是 a。
而 b.html
的内容是:
我是 b。
下面是一个示例代码:
t := template.New("a.html")
if _, err := t.ParseFiles("a.html", "b.html"); err != nil {
panic(err)
}
if err := t.Execute(os.Stdout, nil); err != nil {
panic(err)
}
这个示例创建了一个新的空模板,名称为 a.html
,然后解析了两个文件:a.html
和 b.html
。
结果会是什么呢?t
将表示 a.html
模板,因为我们之前使用了这个特定的名称创建了它。运行代码,输出将是:
我是 a。
现在,如果我们将第一行改为:
t := template.New("x.html")
并保持其余部分不变,运行代码会得到类似的结果:
panic: template: "x.html" 是一个不完整或空的模板
原因是 t
表示一个名为 x.html
的模板,但它是空的,因为我们没有解析任何内容“进入”它,而且解析的文件也没有匹配到 x.html
这个名称。因此,尝试执行它会导致错误。
现在,如果我们尝试执行其中一个关联的命名模板:
if err := t.ExecuteTemplate(os.Stdout, "a.html", nil); err != nil {
panic(err)
}
它会成功,并再次输出:
我是 a。
英文:
First a little about the "template" concept:
A template.Template
value is "the representation of a parsed template". But the wording here is a little "imperfect". A template.Template
value may be (and usually is) a collection of multiple, associated templates. template.Template
has an unexported field:
tmpl map[string]*Template // Map from name to defined templates.
This tmpl
field holds all other associated templates, templates that are visible to the template, and which can be referred to by their names.
You can read more about this in this answer: https://stackoverflow.com/questions/41176355/go-template-name/41187671#41187671
Back to the Template.ParseFiles()
method. This method parses multiple templates from the files passed to it as parameters. The templates parsed form the files will be named after the file names (without folders, just the file name), and they will be added to the internal, associated templates map of the t
template designated by the method receiver.
The parsed templates will not be appended. Multiple, separate template.Template
values will be created for them, but they will be associated (so they can refer to each other, e.g. they can include each other).
Let's see an example. Let's assume we have these 2 template files:
a.html
is:
I'm a.
And b.html
:
I'm b.
And an example code:
t := template.New("a.html")
if _, err := t.ParseFiles("a.html", "b.html"); err != nil {
panic(err)
}
if err := t.Execute(os.Stdout, nil); err != nil {
panic(err)
}
This example creates a new, empty template named a.html
, then parses 2 files: a.html
and b.html
.
What will be the result? t
will denote the a.html
template, because we created it prior with that specific name. Running the code, the output will be:
I'm a.
Now if we change the first line to:
t := template.New("x.html")
And leave the rest unchanged, running it we see something similar:
panic: template: "x.html" is an incomplete or empty template
The reason is that t
denotes a template named x.html
but it's empty, as we didn't parse anything "into" it, and the parsed files also didn't match the name x.html
. So attempting to execute it results in an error.
Now if we try to execute one of its associated, named template:
if err := t.ExecuteTemplate(os.Stdout, "a.html", nil); err != nil {
panic(err)
}
It succeeds, and again gives:
I'm a.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论