2016-12-16 51 views
9

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

回答

10

模板的名称 - 令人惊讶的是 - 名称模板。

这有什么好处?只要你不想参考到模板,它并不重要。但是如果你想参考它,那么是的,你可以通过它的名称来引用它。

什么时候你想参考它?当您想要在另一个例如使用{{template}}操作,或者当您想要使用Template.ExecuteTemplate()执行特定模板时。

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

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

tmpl字段保存的所有其他相关的方案,这是对模板可见的模板,并且可以被称为通过其到-YES-。

当你解析多个一次模板,使用Template.ParseFiles()Template.ParseGlob(),那么模板将通过文件名命名的,它们将被自动关联(上述函数返回一个template.Template值,它包含所有解析的模板,关联)。Template.ParseFiles()的文档清楚如下:

ParseFiles创建一个新的模板并分析来自命名文件的模板定义。返回的模板名称将具有第一个文件的基本名称和解析内容。 [...]

当在不同目录中解析具有相同名称的多个文件时,最后提到的那个文件将会是结果。例如,ParseFiles(“a/foo”,“b/foo”)存储“b/foo”作为名为“foo”的模板,而“a/foo”不可用。

模板名称来自多个地方

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

然后这里发生的是,我们assi将新的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". 

它现在应该是显而易见的模板名称的角色是什么,以及它来自哪里。

4

它是用来渲染的相关模板。

例如:

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)将使用 “基地” 模板

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

+0

除了如果我将第一行更改为'template.New(“”)',那么它的工作原理也是如此。 https://play.golang.org/p/zQoGalIxFq 但我认为你在做某件事。没有命名“基本”模板,ExecuteTemplate似乎不起作用。 – Dave

+0

下面是同样的例子,但是所有模板名称均为空字符串。 https://play.golang.org/p/0NdJ1j_ype它看起来像'{{define'name“}}'可以替代'New'方法中的模板。 – Dave

+0

@Dave我添加了第三个模板以更好地说明命名模板的实用程序。 – jmaloney