如何使用结构或变量值的字段作为模板名称? [英] How to use a field of struct or variable value as template name?

查看:22
本文介绍了如何使用结构或变量值的字段作为模板名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

We can define template name via {{define "home"}}, and then load it in other (parent) template via {{template "home"}}.

如何通过变量值{{template .TemplateName}} 加载模板.还是不可能?

How I can load template via variable value {{template .TemplateName}}. Or it's impossible?

推荐答案

很遗憾你不能.

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

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

The name of the template to be included is a constant string, it is not a pipeline which could vary during execution based on parameters.

如果允许的语法是:

{{template pipeline}}

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

then you could use something like {{template .TemplName}} but since the syntax only allows a constant string, you can't.

来自 Rob 的推理为什么不允许动态模板调用(source):

Reasoning from Rob why dynamic template invocation is not allowed (source):

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

We want the template language to be statically analyzable so the context of a template's invocation is clear, checkable, and lockdownable. If an invocation point is totally dynamic, this can't be done. Similarly, if a template can belong to multiple sets, its context can differ between sets in a way that would require all sets to be analyzed simultaneously. Since both these constraints are easy to work around if you want to, at the cost of losing those static checks in a higher-level package, it seemed wise to control the situation in the base template implementation. A higher-level package, such as a hypothetical HTML-only wrapper, can guarantee no workarounds more easily if the constraints are clear.

替代方案 #1:首先执行可包含模板

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

Alternative #1: Execute Includable Template First

What you can do is execute the template you would want to include first, and insert the result where you want to include it. You can use special types not to escape the result of the inner template when inserting, for example html.HTML in case of HTML templates.

看这个例子:

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:

The result of template t1 was inserted unescaped. If you leave out template.HTML:

params.Value = b.String()

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

t1 would be inserted escaped, like this:

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

替代方案 #2:重构模板

您可以重构您的模板,以免出现您想要包含具有不同名称的模板的情况.

Alternative #2: Restructure Templates

You can restructure your templates not to be in situations where you would want to include a template with varying names.

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

Example: you might want to create pages where you have a page template something like this:

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

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

You can restructure it to be something like this:

header 模板:

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

footer 模板:

    Footers
</body></html

你的页面模板将包括 headerfooter 像这样:

And your page templates would include header and footer like this:

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

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

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

Alternative #3: Use {{if}} action and predefined names

If you know the template names prior and it is not an exhausting list, you can use the {{if}} template action to include the desired template. Example:

{{if eq .Name "page1"}}

    {{template "page1" .}}

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

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

{{end}}

替代方法 #4:修改静态模板文本

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

Alternative #4: Modifying the static template text

The idea here is that you could modify the static text of the outer template manually and insert the name of the inner template you want to include.

这种方法的缺点是插入了内部模板的名字后,还得重新解析模板,所以不推荐这个.

The downside of this method is that after inserting the name of the inner template, you have to re-parse the template, so I don't recommend this.

这篇关于如何使用结构或变量值的字段作为模板名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆