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

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

问题描述

我们可以通过 {{definehome}} 来定义模板名称,然后通过 {{模板home}}



如何通过变量值 {{template .TemplateName}} 。或者它是不可能的?

解决方案

不幸的是, {{template}} 动作的语法:

  {{模板名称}} 
具有指定名称的模板以零数据执行。

{{templatenamepipeline}}
具有指定名称的模板以点设置
执行到管道的值。

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



如果允许的语法是:

  {{template pipeline}} 

然后你可以使用像 {{template .TemplName}} 之类的东西,但是因为语法只允许一个常量字符串,所以你不能。



Rob为什么不允许动态模板调用(
$ b


我们希望模板语言是静态分析的,因此模板调用的上下文是清除,可检查和可锁定。如果一个调用点是完全动态的,这是不能做到的。同样,如果一个模板可以属于多个集合,它的上下文可以在不同集合之间以不同的方式进行分析,这将需要同时分析所有集合。由于这两个约束都可以很容易地解决,如果需要的话,以在较高级别的包中丢失这些静态检查为代价,控制基本模板实现中的情况似乎是明智的。一个更高级别的软件包,比如一个假设的仅包含HTML的包装器,如果约束条件清晰,可以更容易地保证没有解决方法。




选择#1:执行可包含的模板首先



你可以做的是执行你想要包含的模板,然后将结果插入到要包含的模板中。您可以使用特殊类型来避免在插入时逃避内部模板的结果,例如 html.HTML 在HTML模板的情况下。



请看这个例子:

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

params:= struct {
名称字符串
接口{}
} {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>
现在我将包含名称为{{.Name}}
{{.Value}}
< / body> / html>`

const t1 =`我是模板< b> t1< / b>。

输出:

 < html>< body> 
现在我将包含名称为模板:t1
我是模板< b> t1< / b> ;.
< / body> / html>

试试 Go Playground



模板 t1 插入未转义。如果您省略 template.HTML

  params.Value = b .String()

t1 像这样:

 < html>< body> 
现在我将包含名称为:t1
I& m模板< b& gt; t1& lt; / b& gt;的模板。
< / body> / html>



选择#2:重组模板



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


$ b 示例:您可能想要创建包含 page 模板如下所示:

 < html>< body> 
标题,标题等
{{template .Page}}
页脚
< / body>< / html>

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


$ b $
$ b $ $ p $ < html>< b>< code>体>
标题,标题等

页脚 $ b

 页脚
< / body>< / html

您的页面模板将包含标题页脚



  {{templateheader。}} 
Page content这里。
{{templatefooter。}}



选择#3:使用<$ c

如果您事先知道模板名称并且它并不令人疲惫,那么您可以可以使用 {{if}} 模板操作来包含所需的模板。示例:

  {{if eq .Namepage1}} 

{{templatepage1 。}}

{{else if eq .Namepage2}}

{{templatepage2。}}
...

{{end}}



选择#4:修改静态模板文本



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



这种方法的缺点是在插入内部模板名称后,必须重新解析模板,所以我不推荐这样做。


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

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

解决方案

Unfortunately you can't.

The syntax of the {{template}} action:

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

If the allowed syntax would be:

{{template pipeline}}

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

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

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.

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.

See this example:

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

Output:

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

Try it on the Go Playground.

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

params.Value = b.String()

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>

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.

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 template:

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

footer template:

    Footers
</body></html

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

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

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

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天全站免登陆