Go模板的ParseFiles函数可以解析多个文件。

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

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.htmlb.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.

huangapple
  • 本文由 发表于 2017年7月8日 04:39:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/44979276.html
匿名

发表评论

匿名网友

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

确定