转到模板名称

Go template name

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`))

https://play.golang.org/p/wKzCHdLf2S

用于呈现关联模板。

例如:

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)

Play Example

输出:

     Start of base template


       Body


     End of base template

     Start of baz template


       Body


     End of baz template

tmpl.ExecuteTemplate(os.Stdout, "base", nil) 将使用 "base" 模板呈现模板

tmpl.ExecuteTemplate(os.Stdout, "baz", nil) 将使用 "baz" 模板呈现模板

模板的名称——毫不奇怪——就是命名模板。

它有什么用?只要您不想引用模板,就没有关系。但是如果你想引用,那么是的,你可以通过它的名称.

来引用它

您想什么时候参考它?当你想在另一个模板中包含一个模板时,例如使用 {{template}} 操作,或者当您想使用 Template.ExecuteTemplate().

执行特定模板时

到目前为止一切顺利,但仍然缺少一个关键点。这不是明确的/微不足道的:template.Template 值是 “已解析模板的表示”。但是这里的措辞有点“不完美”。 template.Template 值可能是(并且通常是) 多个关联模板的集合template.Template 有一个未导出的字段:

tmpl   map[string]*Template // Map from name to defined templates.

tmpl 字段包含所有其他关联的模板,这些模板对模板可见,并且可以通过它们的 名称 进行引用。

当你一次解析多个个模板时,使用Template.ParseFiles() or Template.ParseGlob(),模板将以文件名命名,并自动关联(以上提到的函数 return 单个 template.Template 值,它包含所有已解析的模板,关联)。 Template.ParseFiles() 的文档对此很清楚:

ParseFiles creates a new Template and parses the template definitions from the named files. The returned template's name will have the base name and parsed contents of the first file. [...]

When parsing multiple files with the same name in different directories, the last one mentioned will be the one that results. For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template named "foo", while "a/foo" is unavailable.

模板名称可以来自多个地方:

  • 它可以来自文件名(如上所示)
  • 可以明确指定(如果使用 {{define "somename"}}{{block "somename"}} 操作定义),
  • 或者它可以定义为传递给 template.New() (function) or 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))

然后这里发生的是我们给t分配了一个新的template.Template值,这是解析t2src的结果,所以这将是默认值,但仍然是两者模板可以在关联时从它“到达”。输出更改为(在 Go Playground 上尝试):

I'm some OTHER template.
I'm some template.
I'm some OTHER template.

调用 template.New()(函数)创建一个关联到 none 的新模板。调用 Template.New()(方法)时,returned 模板将与调用该方法的(所有)模板相关联。

现在让我们看一些关于“嵌入式”模板的例子。

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

模板名的作用是什么,从哪里来的,现在应该很明显了。

如果你不需要名字,你可以使用 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")
}