Golang模板引擎管道

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

Golang template engine pipelines

问题

我有一个 Golang 模板,定义如下:

{{- define "test" -}}
{{- printf "%s" .Name | trunc 24 -}}
{{- end -}}

然后我在其中一个文件中使用它:

{{ template "test" . }}

在 "test" 后面的点号代表什么意思?Golang 模板文档中说:

{{template "name" pipeline}}
使用指定名称的模板,并将 dot 设置为 pipeline 的值。

但我不确定 pipeline 是什么意思。阅读文档没有得到结果,有人可以再解释一次吗?

另外,为什么我们必须以点号开头的值?例如 {{ - printf "%s" .Name | trunc 24 -}}。这也是一种 pipeline 吗?

提前谢谢!

英文:

I have a Golang template, defined like this

{{- define "test" -}}
{{- printf "%s" .Name | trunc 24 -}}
{{- end -}}

Then I use it in one of my files:

{{ template "test" . }}

What does the dot mean after "test"? Golang template docs say:

{{template "name" pipeline}}
The template with the specified name is executed with dot set
to the value of the pipeline.

But I am not sure what pipeline is. Reading documentation gave no results, could anyone explain once again?

Also, why do we have to start values beginning with dot? E.g. {{ - printf "%s" .Name | trunc 24 -}}. Is it also a kind of pipeline?

Thank you in advance!

答案1

得分: 20

有两个template包,text/templatehtml/template

它们具有相同的接口,但html/template包用于生成防止代码注入的安全HTML输出,应该在输出为HTML时使用,而不是使用text/template

由于它们具有相同的接口,但html/template提供了一些额外的功能(插入数据的上下文转义),基本原理只在text/html中记录,而html/template的文档主要关注详细说明这些额外功能。

话虽如此,“pipeline”属于基本知识。它在text/templatePipelines部分中有记录:

Pipelines

管道是一系列“命令”的可能链接序列。命令可以是简单值(参数)或函数或方法调用,可能带有多个参数:

Argument
    结果是评估参数的值。
.Method [Argument...]
    方法可以是独立的,也可以是链的最后一个元素,但与链中间的方法不同,它可以接受参数。
    结果是使用参数调用方法的值:
        dot.Method(Argument1, etc.)
functionName [Argument...]
    结果是调用与名称关联的函数的值:
        function(Argument1, etc.)
    函数和函数名称将在下面描述。

通过使用管道字符'|'将一系列命令分隔开,可以将管道“链接”起来。在链接的管道中,每个命令的结果作为以下命令的最后一个参数传递。管道中最后一个命令的输出是管道的值。

“Arguments”和“pipelines”是数据的评估。

“dot”.基本上是一个光标,指向在执行模板时传递的数据结构中的某个位置。点的起始值是您传递的值,但是此点会被许多操作修改,例如{{range}}{{with}}

模板的执行遍历结构并设置光标,用一个句点'.'表示,称为“dot”,将其设置为执行过程中结构中当前位置的值。

因此,当您编写.Name时,这意味着您希望引用当前点指向的值的字段、方法或键称为Name。例如,如果您传递一个struct,在模板的开头,.Name将表示结构字段Name(如果存在)或其名为Name()的方法。

当您调用/包含另一个模板时,您可以告诉要传递给其执行的值。当您编写{{template "something" .}}时,这意味着您希望将当前点指向的值传递给模板执行。如果您只想传递点指向的结构的Name字段,可以像这样进行:{{template "something" .Name}}

{{template}}中作为管道传递的值将成为调用其他模板中的点。

因此,在处理/渲染模板时,点可能会更改并且仅指向最初传递给模板执行的值的一部分。通常情况下,仍然可以访问原始值而不仅仅是光标是很方便或必需的。为此,模板包提供了$

当执行开始时,$被设置为传递给Execute的数据参数,即点的起始值。

因此,即使您在{{range}}中(它将点设置为数组/切片/映射的连续元素),您仍然可以访问并引用传递给模板执行的值的任何其他部分。

因此,例如,如果您正在遍历一个书籍的切片,如{{range .Books}},并且如果您需要最初传递的结构的Name字段,您可以在{{range}}内部这样做:

{{range .Books}}
    标题:{{.Title}}
    原始名称:{{$.Name}}
{{end}}
英文:

There are 2 template packages, text/template and html/template.

They have the same interface, but the html/template package is for generating HTML output safe against code injection, and should be used instead of text/template whenever the output is HTML.

Since they have the same interface but the html/template provides some extra functionality (contextual escaping of the inserted data), the basics and principles are only documented at text/html, and the documentation of html/template mostly focuses on detailing the extra.

That being said, "pipeline" belongs to the basics. It is documented in text/template, section Pipelines:

> ### Pipelines

> A pipeline is a possibly chained sequence of "commands". A command is a simple value (argument) or a function or method call, possibly with multiple arguments:

> Argument
The result is the value of evaluating the argument.
.Method [Argument...]
The method can be alone or the last element of a chain but,
unlike methods in the middle of a chain, it can take arguments.
The result is the value of calling the method with the
arguments:
dot.Method(Argument1, etc.)
functionName [Argument...]
The result is the value of calling the function associated
with the name:
function(Argument1, etc.)
Functions and function names are described below.

> A pipeline may be "chained" by separating a sequence of commands with pipeline characters '|'. In a chained pipeline, the result of each command is passed as the last argument of the following command. The output of the final command in the pipeline is the value of the pipeline.

"Arguments" and "pipelines" are evaluations of data.

The "dot" . is basically a cursor, pointing to somewhere in the data structure you pass when executing the template. The starting value of the dot is the value you pass, but this dot is modified by many actions, such as {{range}} or {{with}}.

> Execution of the template walks the structure and sets the cursor, represented by a period '.' and called "dot", to the value at the current location in the structure as execution proceeds.

So when you write .Name, that means that the value where dot is pointing currently, you want to refer to its field or method or key called Name. For example if you pass a struct, at the beginning of your template .Name will denote the struct field Name if it exists, or its method named Name().

When you invoke / include another template, you have the possibility to tell what value you what to pass to its execution. When you write {{template "something" .}}, that means you want to pass the value currently pointed by dot to the template execution. If you want to pass only the Name field of the struct pointed by the dot, you may do it like {{template "something" .Name}}.

The value you pass as the pipeline in {{template}} will become the dot inside the invoked other template.

So as your template is being processed / rendered, the dot may be changed and point "only" to a part of the value originally passed to your template execution. Often it's handy or required to still reach the original value and not just the cursor. For this the template package provides the $:

> When execution begins, $ is set to the data argument passed to Execute, that is, to the starting value of dot.

So even if you're inside a {{range}} for example (which sets the dot to the successive elements of the array / slice / map you're ranging over), you can still reach out and refer to any other parts of the value passed to the template execution.

So for example if you're ranging over a slice of books like {{range .Books}}, and if you need the Name field of the originally passed struct, you may do it inside {{range}} like this:

{{range .Books}}
    Title: {{.Title}}
    Original name: {{$.Name}}
{{end}}

huangapple
  • 本文由 发表于 2017年2月28日 19:47:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/42507958.html
匿名

发表评论

匿名网友

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

确定