12

我们可以通过 定义模板名称{{define "home"}},然后通过 将其加载到其他(父)模板中{{template "home"}}

如何通过变量 value 加载模板{{template .TemplateName}}。或者这是不可能的?

4

1 回答 1

23

不幸的是你不能。

动作的语法{{template}}

{{template "name"}}
    The template with the specified name is executed with nil data.

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

要包含的模板的名称是一个常量字符串,它不是一个在执行过程中会根据参数而变化的管道。

如果允许的语法是:

{{template pipeline}}

那么你可以使用类似的东西,{{template .TemplName}}但由于语法只允许一个常量字符串,你不能。

从 Rob 推理为什么不允许动态模板调用(来源):

我们希望模板语言是静态可分析的,因此模板调用的上下文是清晰的、可检查的和可锁定的。如果调用点是完全动态的,则无法做到这一点。类似地,如果一个模板可以属于多个集合,那么它的上下文在集合之间可能会有所不同,这需要同时分析所有集合。由于如果您愿意,这两个约束都很容易解决,但代价是在更高级别的包中丢失了这些静态检查,控制基本模板实现中的情况似乎是明智的。如果约束明确,则更高级别的包(例如假设的仅 HTML 包装器)可以更轻松地保证没有变通方法。

备选方案#1:首先执行可包含的模板

您可以做的是首先执行您想要包含的模板,然后将结果插入您想要包含它的位置。您可以使用特殊类型在插入时不转义内部模板的结果,例如html.HTML在 HTML 模板的情况下。

看这个例子:

func main() {
    t := template.Must(template.New("t").Parse(t))
    template.Must(t.New("t1").Parse(t1))

    params := struct {
        Name  string
        Value interface{}
    }{"t1", nil}
    b := bytes.Buffer{}
    t.ExecuteTemplate(&b, params.Name, nil)
    params.Value = template.HTML(b.String())

    t.Execute(os.Stdout, params)
}

const t = `<html><body>
Now I will include template with name: {{.Name}}
{{.Value}}
</body>/html>`

const t1 = `I'm template <b>t1</b>.`

输出:

<html><body>
Now I will include template with name: t1
I'm template <b>t1</b>.
</body>/html>

在Go Playground上尝试一下。

模板的结果t1未转义插入。如果您遗漏template.HTML

params.Value = b.String()

t1将被插入转义,如下所示:

<html><body>
Now I will include template with name: t1
I&#39;m template &lt;b&gt;t1&lt;/b&gt;.
</body>/html>

备选方案#2:重组模板

您可以重组您的模板,使其不会出现在您希望包含具有不同名称的模板的情况下。

示例:您可能希望创建具有page如下模板的页面:

<html><body>
    Title, headers etc.
    {{template .Page}}
    Footers
</body></html>

您可以将其重组为如下所示:

header模板:

<html><body>
    Title, headers, etc.

footer模板:

    Footers
</body></html

您的页面模板将包括header这样的footer

{{template "header" .}}
    Page content comes here.
{{template "footer" .}}

备选方案 #3:使用{{if}}操作和预定义名称

如果您事先知道模板名称并且它不是一个详尽的列表,您可以使用{{if}}模板操作来包含所需的模板。例子:

{{if eq .Name "page1"}}

    {{template "page1" .}}

{{else if eq .Name "page2"}}

    {{template "page2" .}}
    ...

{{end}}

备选方案#4:修改静态模板文本

这里的想法是您可以手动修改外部模板的静态文本并插入要包含的内部模板的名称。

这种方法的缺点是插入了内部模板的名字后,需要重新解析模板,所以不推荐这种方式。

于 2015-03-03T11:52:23.330 回答