doubi4340 2015-03-03 11:21
浏览 65
已采纳

如何使用结构或变量值的字段作为模板名称?

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?

  • 写回答

1条回答 默认 最新

  • doulie0178 2015-03-03 11:52
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥60 pb数据库修改或者求完整pb库存系统,需为pb自带数据库
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路