Golang模板 – 如何渲染模板?

huangapple go评论73阅读模式
英文:

Golang template - how to render templates?

问题

一个包含三个子模板的布局模板。

layout.html

<html>
  <body>
    {{template "tags"}}
    
    {{template "content"}}
              
    {{template "comment"}}
  </body>
</html>

tags.html

{{define "tags"}}
<div>
    {{.Name}}
<div>
{{end}}

content.html

{{define "content"}}
<div>
   <p>{{.Title}}</p>
   <p>{{.Content}}</p>
</div>
{{end}}

comment.html

{{define "tags"}}
<div>
    {{.Note}}
</div>
{{end}}

##gocode

type Tags struct {
   Id int
   Name string
}

type Content struct {
   Id int
   Title string
   Content string
}

type Comment struct {
   Id int
   Note string
}


func main() {
    tags := &Tags{"Id":1, "Name":"golang"}
    Content := &Content{"Id":9, "Title":"Hello", "Content":"World!"}
    Comment := &Comment{"Id":2, "Note":"Good Day!"}
}

我不确定如何渲染每个子模板并将结果组合到布局输出中。

谢谢。

英文:

One layout template with three children templates.

layout.html

<html>
  <body>
    {{template "tags"}}
    
    {{template "content"}}
              
    {{template "comment"}}
  </body>
</html>

tags.html

{{define "tags"}}
<div>
    {{.Name}}
<div>
{{end}}

content.html

{{define "content"}}
<div>
   <p>{{.Title}}</p>
   <p>{{.Content}}</p>
</div>
{{end}}

comment.html

{{define "tags"}}
<div>
    {{.Note}}
</div>
{{end}}

##gocode

type Tags struct {
   Id int
   Name string
}

type Content struct {
   Id int
   Title string
   Content string
}

type Comment struct {
   Id int
   Note string
}


func main() {
    tags := &Tags{"Id":1, "Name":"golang"}
    Content := &Content{"Id":9, "Title":"Hello", "Content":"World!"}
    Comment := &Comment{"Id":2, "Note":"Good Day!"}
}

I am confused that how to render each children template and combine the result to layout output.

Thanks.

答案1

得分: 26

如往常一样,文档是一个很好的起点。

我在游乐场上写了一个可工作的示例。

简要解释一下:

  1. 在结构体字面量中不需要使用字符串:&Tags{Id: 1},而不是&Tags{"Id":1}
  2. 你只能传递一个对象给模板执行,它会根据你在{{template <name> <arg>}}指令中的要求将对象分派给每个子模板。我使用了一个临时的Page结构体,但如果你喜欢的话,也可以使用map[string]interface{}
  3. 你需要解析每个模板(我在游乐场上使用了字符串,但如果你已经有了HTML文件,可以使用ParseFiles
  4. 我使用了os.Stdout来执行它,但你显然应该将其替换为相应的ResponseWriter

以下是完整的代码:

package main

import "fmt"
import "html/template"
import "os"

var page = `<html>
  <body>
    {{template "tags" .Tags}}

    {{template "content" .Content}}

    {{template "comment" .Comment}}
  </body>
</html>`

var tags = `{{define "tags"}}
<div>
    {{.Name}}
<div>
{{end}}`

var content = `{{define "content"}}
<div>
   <p>{{.Title}}</p>
   <p>{{.Content}}</p>
</div>
{{end}}`

var comment = `{{define "comment"}}
<div>
    {{.Note}}
</div>
{{end}}`

type Tags struct {
   Id   int
   Name string
}

type Content struct {
   Id      int
   Title   string
   Content string
}

type Comment struct {
   Id   int
   Note string
}

type Page struct {
    Tags    *Tags
    Content *Content
    Comment *Comment
}

func main() {
    pagedata := &Page{
        Tags:    &Tags{Id: 1, Name: "golang"},
        Content: &Content{Id: 9, Title: "Hello", Content: "World!"},
        Comment: &Comment{Id: 2, Note: "Good Day!"},
    }
    tmpl := template.New("page")
    var err error
    if tmpl, err = tmpl.Parse(page); err != nil {
        fmt.Println(err)
    }
    if tmpl, err = tmpl.Parse(tags); err != nil {
        fmt.Println(err)
    }
    if tmpl, err = tmpl.Parse(comment); err != nil {
        fmt.Println(err)
    }
    if tmpl, err = tmpl.Parse(content); err != nil {
        fmt.Println(err)
    }
    tmpl.Execute(os.Stdout, pagedata)
}
英文:

As always, the doc is a good place to start.

I wrote a working example on the playground

To explain a bit:

  1. You don't need strings in struct literals: &amp;Tags{Id: 1}, not &amp;Tags{&quot;Id&quot;:1}
  2. You can only pass a single object to your template to execute, which will dispatch objects to each subtemplate as you require in the {{template &lt;name&gt; &lt;arg&gt;}} instruction. I used a ad-hoc Page struct, but a map[string]interface{} would do if you prefer.
  3. You need to parse each template (I used strings in the Playground, but ParseFiles would do if you have your html files already)
  4. I used os.Stdout to execute it, but you should obviously replace that by the corresponding ResponseWriter

And the whole code:

package main
import &quot;fmt&quot;
import &quot;html/template&quot;
import &quot;os&quot;
var page = `&lt;html&gt;
&lt;body&gt;
{{template &quot;tags&quot; .Tags}}
{{template &quot;content&quot; .Content}}
{{template &quot;comment&quot; .Comment}}
&lt;/body&gt;
&lt;/html&gt;`
var tags = `{{define &quot;tags&quot;}}
&lt;div&gt;
{{.Name}}
&lt;div&gt;
{{end}}`
var content = `{{define &quot;content&quot;}}
&lt;div&gt;
&lt;p&gt;{{.Title}}&lt;/p&gt;
&lt;p&gt;{{.Content}}&lt;/p&gt;
&lt;/div&gt;
{{end}}`
var comment = `{{define &quot;comment&quot;}}
&lt;div&gt;
{{.Note}}
&lt;/div&gt;
{{end}}`
type Tags struct {
Id int
Name string
}
type Content struct {
Id int
Title string
Content string
}
type Comment struct {
Id int
Note string
}
type Page struct {
Tags *Tags
Content *Content
Comment *Comment
}
func main() {
pagedata := &amp;Page{Tags:&amp;Tags{Id:1, Name:&quot;golang&quot;},
Content: &amp;Content{Id:9, Title:&quot;Hello&quot;, Content:&quot;World!&quot;},
Comment: &amp;Comment{Id:2, Note:&quot;Good Day!&quot;}}
tmpl := template.New(&quot;page&quot;)
var err error
if tmpl, err = tmpl.Parse(page); err != nil {
fmt.Println(err)
}
if tmpl, err = tmpl.Parse(tags); err != nil {
fmt.Println(err)
}
if tmpl, err = tmpl.Parse(comment); err != nil {
fmt.Println(err)
}
if tmpl, err = tmpl.Parse(content); err != nil {
fmt.Println(err)
}
tmpl.Execute(os.Stdout, pagedata)
}

huangapple
  • 本文由 发表于 2013年10月24日 00:11:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/19546896.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定