去模板名称

时间:2016-12-16 02:24:41

标签: go go-templates

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

3 个答案:

答案 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 = '_')    

Play Example

输出:

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")
}