Templates 如何传递多个要转到的对象模板?

Templates 如何传递多个要转到的对象模板?,templates,go,Templates,Go,我能找到的大多数示例都描述了非常简单/基本的事情,例如显示person对象的属性,如下所示: The name is {{.Name}}. The age is {{.Age}}. {{p.Name}} is aged {{p.Age}}. Outstanding invoices {{invoices.Count}} <table> <tr><td>{{invoices[0].number}}</td></tr> .... e

我能找到的大多数示例都描述了非常简单/基本的事情,例如显示person对象的属性,如下所示:

The name is {{.Name}}. The age is {{.Age}}.
{{p.Name}} is aged {{p.Age}}. 
Outstanding invoices {{invoices.Count}} 

<table>
<tr><td>{{invoices[0].number}}</td></tr>
.... etc...
templ.Execute(file, struct {
    Age int
    Name string
}{42, "Dolphin"})
如果您有一个更复杂的网页,例如,多个不同的对象和对象列表,会发生什么情况,即如何执行以下操作:

The name is {{.Name}}. The age is {{.Age}}.
{{p.Name}} is aged {{p.Age}}. 
Outstanding invoices {{invoices.Count}} 

<table>
<tr><td>{{invoices[0].number}}</td></tr>
.... etc...
templ.Execute(file, struct {
    Age int
    Name string
}{42, "Dolphin"})
{{p.Name}}已老化{p.Age}。
未付发票{{invoices.Count}
{{发票[0]。编号}
.... 等

您可以将更复杂的数据放入struct,并像传递
Name
Age
一样传递它。比如说,

type vars struct {
    P User
    Invoices []Invoice
}

type User struct {
    Name string
    Age int
}

type Invoice {
    Number int
    Description string
}
如果将
vars
的实例传递到模板执行中,则可以使用点和数组索引引用子结构,就像在常规go代码中一样

{{.P.Name}}, {{.P.Age}}, {{.Invoices[0].Number}}

这取决于你的数据是什么。 我想把它分类

  • 模板用于的主要数据。在您的示例中,这将是发票/发票列表。如果您必须通过其中一个以上的测试,则必须重新考虑模板设计
  • 辅助数据,例如登录的用户信息或您发现自己传递到多个模板中的任何公共信息
  • 因为这些信息是常见的。我通常把它们做成函数。因为这些函数不能有输入参数。您可能希望将它们创建为闭包(在另一个函数中)。将这些函数分配给funMap,并在解析后将其添加到模板中

    func MakeFuncMap(u *user) map[string]interface{} {
        return map[string]interface{}{
            "User": func() *user {return u}, //Can be accessed by "User." within your template
        }
    }
    
    t, err := template.New("tmpl").Funcs(MakeFuncMap(nil)).Parse("template") //You will need to append a dummy funcMap as you will not have access to User at the time of template parsing
    
    //You will have to clone the template to make it thread safe to append funcMap.
    tClone, _ := t.Clone()
    tClone.Funcs(MakeFuncMap(u)).Execute(w, invoicelist)
    
    现在,您可以仅使用invoicelist作为数据执行模板。 在模板中,您应该能够使用“用户”和“发票列表依据”访问用户信息

    您应该能够为所有公共数据定义一次funcMap。这样您就可以重用它了

    要循环查看发票列表,可以查看范围

    {{range .}} //if you are passing invoicelist then the . means invoicelist
       //in here . means each of the invoice
       <label>{{User.Name}}, {{User.Age}}</label>
       <label>{{.Id}}</label>
    {{end}}
    
    {{range.}}//如果要传递invoicelist,则。指发票清单
    //在这里。指发票中的每一项
    {{User.Name},{{User.Age}
    {{.Id}
    {{end}
    

    编辑:包含对Ripoune指出的问题的修复,您可以声明并传入一个匿名结构,如下所示:

    The name is {{.Name}}. The age is {{.Age}}.
    
    {{p.Name}} is aged {{p.Age}}. 
    Outstanding invoices {{invoices.Count}} 
    
    <table>
    <tr><td>{{invoices[0].number}}</td></tr>
    .... etc...
    
    templ.Execute(file, struct {
        Age int
        Name string
    }{42, "Dolphin"})
    
    并访问以下变量:

    {{.Age}}, {{.Name}}
    

    虽然这仍然需要创建结构,但它是最简洁的方法之一。你必须决定它对你来说是否太难看;)

    会有帮助吗?使用结构作为管道可以解决简单的情况。更一般/复杂的情况会变得麻烦,请参阅我得到的相关问题,您可以为struct创建一个struct,但这是否意味着您必须为系统中的每个网页创建一个struct?如果你有100页,那会发生什么?看起来有点难以管理?你会使用什么命名系统?ie HomePageTemplate具有HomePageStruct等…@Jacob您不需要结构。您还可以使用
    map[string]接口{}
    。tbh为页面使用结构并不是真的错误。它确实可以使数据得到更好的记录,从而更好地管理。此外,您可以使用结构组合或仅重用具有相同参数的页面。这在webapp中看起来非常危险,因为不幸的是,生成的模板不是线程安全的,用户将意外共享相同的用户函数。看,还有@Ripounet,你是对的。谢谢你指出这一点。但是我过去常常在添加函数映射之前在模板上进行克隆。如果您之前在解析模板时附加了一个伪func映射(像您所做的那样使用jst),则可以这样做。看见我想知道这是不是一个好的方法。再次感谢。虽然我不知道如何编辑答案而不引起混乱,但我没有想到要克隆模板。衡量性能影响会很有趣。克隆工作在source Yea中有描述,性能也是我担心的部分。。。我在我的工作站上工作,克隆在程序执行时间上增加了12%的开销。不克隆:,克隆:我想你在那个例子中有一个无关的“struct{”。@dotpaul我同意,这个例子已经修复了。谢谢!