在html/template
(和text/template
)个套餐中,template.New
具有以下签名:
func New(name string) *Template
name
究竟用于什么?我已经扫描了文档(以及一些来源),但无济于事。我只是用空字符串实例化我的所有模板,它似乎没有什么区别。我为什么要打扰一个名字?
即使对于命名模板,这两者似乎是等价的:
template.Must(template.New("").Parse(`{{ define "body" }}Body{{ end }}`))
template.Must(template.New("body").Parse(`Body`))
答案 0 :(得分:30)
模板的名称 - 不出所料 - 是名称模板。
有什么好处?只要你不想引用到模板,它就没关系了。但是,如果您想引用,那么是的,您可以通过名称来引用它。
你什么时候想参考它?当您想要在另一个模板中包含模板时使用{{template}}
操作,或者当您想使用Template.ExecuteTemplate()
执行特定模板时。
到目前为止一直很好,但仍有一个缺失的关键点。这不是明确/平凡的:template.Template
值是“解析模板的表示”。但这里的措辞有点“不完美”。 template.Template
值可能(通常是)多个相关模板的集合。 template.Template
有一个未列出的字段:
tmpl map[string]*Template // Map from name to defined templates.
此tmpl
字段包含所有其他关联的模板,模板可见的模板,以及可由名称引用的模板。
当您使用Template.ParseFiles()
或Template.ParseGlob()
一次解析多个模板时,模板将按文件名命名,并且它们将自动关联(上面提到的函数返回一个template.Template
值,它包含所有已解析的模板,相关联的)。 Template.ParseFiles()
的文件清楚明了:
ParseFiles创建一个新模板并从命名文件中解析模板定义。返回的模板名称将具有第一个文件的基本名称和已解析的内容。 [...]
在不同目录中解析具有相同名称的多个文件时,提到的最后一个文件将是结果。例如,ParseFiles(“a / foo”,“b / foo”)将“b / foo”存储为名为“foo”的模板,而“a / foo”则不可用。
模板名称可以来自多个地方:
{{define "somename"}}
或{{block "somename"}}
操作定义),template.New()
(函数)或Template.New()
(方法)的参数。让我们看一些例子:
func main() {
t := template.Must(template.New("one").Parse(t1src))
template.Must(t.New("other").Parse(t2src))
// error checks omitted for brevity
// Executes default, "one":
t.Execute(os.Stdout, nil)
// Executes explicit, "one":
t.ExecuteTemplate(os.Stdout, "one", nil)
// Executes explicit, "other":
t.ExecuteTemplate(os.Stdout, "other", nil)
}
const t1src = `I'm some template.
`
const t2src = `I'm some OTHER template.
`
输出(在Go Playground上尝试):
I'm some template.
I'm some template.
I'm some OTHER template.
如果您现在继续,请将前两行更改为:
t := template.Must(template.New("one").Parse(t1src))
t = template.Must(t.New("other").Parse(t2src))
然后,这里发生的是我们为template.Template
分配了一个新的t
值,这是解析t2src
的结果,因此这将是默认值,但两个模板仍然可以因为它们是相关联的,所以从它“到达”。输出更改为此(在Go Playground上尝试):
I'm some OTHER template.
I'm some template.
I'm some OTHER template.
调用template.New()
(函数)会创建一个与之无关的新模板。调用Template.New()
(方法)时,返回的模板将与调用该方法的模板(全部)相关联。
现在让我们看一些关于“嵌入式”模板的例子。
func main() {
t := template.Must(template.New("one").Parse(t1src))
template.Must(t.New("other").Parse(t2src))
template.Must(t.New("third").Parse(t3src))
t.Execute(os.Stdout, nil)
t.ExecuteTemplate(os.Stdout, "one", nil)
t.ExecuteTemplate(os.Stdout, "other", nil)
t.ExecuteTemplate(os.Stdout, "embedded", nil)
t.ExecuteTemplate(os.Stdout, "third", nil)
}
const t1src = `I'm some template. {{block "embedded" .}}I'm embedded in "one".
{{end}}`
const t2src = `I'm some OTHER template.
`
const t3src = `I'm the 3rd, including everything from "one": {{template "one"}}
`
输出(在Go Playground上尝试):
I'm some template. I'm embedded in "one".
I'm some template. I'm embedded in "one".
I'm some OTHER template.
I'm embedded in "one".
I'm the 3rd, including everything from "one": I'm some template. I'm embedded in "one".
现在应该很清楚模板名称的作用是什么,以及它来自何处。
答案 1 :(得分:3)
用于渲染相关模板。
例如:
01 _102 1001010101 $ a r $0b1R b1b0L a1b2R
input tape input start accept reject transitions
| alphabets | | states |
(blank = '_')
输出:
tmpl := template.Must(template.New("body").Parse(`
{{ define "body" }}
Body
{{ end }}
`))
tmpl = template.Must(tmpl.New("base").Parse(`
Start of base template
{{ template "body" }}
End of base template
`))
tmpl = template.Must(tmpl.New("baz").Parse(`
Start of baz template
{{ template "body" }}
End of baz template
`))
tmpl.ExecuteTemplate(os.Stdout, "base", nil)
tmpl.ExecuteTemplate(os.Stdout, "baz", nil)
Start of base template
Body
End of base template
Start of baz template
Body
End of baz template
将使用" base"呈现模板模板
tmpl.ExecuteTemplate(os.Stdout, "base", nil)
将使用" baz"呈现模板模板
答案 2 :(得分:0)
如果您不需要名称,您可以使用内置的 new
template.Template:
package main
import (
"os"
"text/template"
)
func main() {
t, err := new(template.Template).Parse("hello {{.}}\n")
if err != nil {
panic(err)
}
t.Execute(os.Stdout, "world")
}