Range through an arbitrary number of nested slices of structs in an HTML template in Go

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

Range through an arbitrary number of nested slices of structs in an HTML template in Go

问题

我正在尝试构建一个类似Reddit的网络论坛。有顶级帖子和回复,回复可以有回复,依此类推。

一个板块的结构如下:

  1. var board map[string]*Post

以及一个Post的结构:

  1. type Post struct {
  2. Title string
  3. Body string
  4. ID string
  5. PostNum int
  6. Replies []*Post
  7. }

我该如何使用模板来遍历嵌套的Replies切片(要记住每个*Post都包含一个包含*PostsReplies切片,依此类推)?

我目前的进展:

  1. <div id="posts">
  2. {{ .Title }}
  3. {{ .Body }}
  4. <ul>
  5. {{ range $key, $value := .Replies }}
  6. <li class="post">
  7. <div class="postHead">
  8. <div class="postTitle"><b>{{ $value.ID }}</b></div>
  9. </div>
  10. <div class="postBody">{{ $value.PostNum }}</div>
  11. </li>
  12. <ul>
  13. {{ range $key, $value := $value.Replies }}
  14. <li class="post">
  15. <div class="postHead">
  16. <div class="postTitle"><b>{{ $value.ID }}</b></div>
  17. </div>
  18. <div class="postBody">{{ $value.PostNum }}</div>
  19. </li>
  20. {{ end }}
  21. </ul>
  22. {{ end }}
  23. </ul>
  24. </div>

这只允许我遍历两层回复(并且如你所见使用了重复的代码),我需要能够遍历任意层级的Replies

英文:

I'm trying to build a web forum kind of like Reddit. There are top level posts with replies and the replies can have replies and so on.

A board looks like this:

  1. var board map[string]*Post

and a Post:

  1. type Post struct {
  2. Title string
  3. Body string
  4. ID string
  5. PostNum int
  6. Replies []*Post
  7. }

How would I use a template to range through the nested Replies slices (keeping in mind that each *Post contains a Replies slice that contains *Posts that contains Replies and so on)?

What I have so far:

  1. &lt;div id=&quot;posts&quot;&gt;
  2. {{ .Title }}
  3. {{ .Body }}
  4. &lt;ul&gt;
  5. {{ range $key, $value := .Replies }}
  6. &lt;li class=&quot;post&quot;&gt;
  7. &lt;div class=&quot;postHead&quot;&gt;
  8. &lt;div class=&quot;postTitle&quot;&gt;&lt;b&gt;{{ $value.ID }}&lt;/b&gt;&lt;/div&gt;
  9. &lt;/div&gt;
  10. &lt;div class=&quot;postBody&quot;&gt;{{ $value.PostNum }}&lt;/div&gt;
  11. &lt;/li&gt;
  12. &lt;ul&gt;
  13. {{ range $key, $value := $value.Replies }}
  14. &lt;li class=&quot;post&quot;&gt;
  15. &lt;div class=&quot;postHead&quot;&gt;
  16. &lt;div class=&quot;postTitle&quot;&gt;&lt;b&gt;{{ $value.ID }}&lt;/b&gt;&lt;/div&gt;
  17. &lt;/div&gt;
  18. &lt;div class=&quot;postBody&quot;&gt;{{ $value.PostNum }}&lt;/div&gt;
  19. &lt;/li&gt;
  20. {{ end }}
  21. &lt;/ul&gt;
  22. {{ end }}
  23. &lt;/ul&gt;
  24. &lt;/div&gt;

This only allows me to range through two levels of replies (and as you can see uses duplicate code), I need to be able to range through an arbitrary number of levels of Replies.

答案1

得分: 7

要递归遍历一个层次结构,可以使用一个执行自身的命名模板。在下面的示例中,模板"replies"执行"replies"以显示子回复:

  1. {{define "main"}}
  2. <div id="post">
  3. {{.Title}}
  4. {{.Body}}
  5. {{template "replies" .Replies}}
  6. </div>
  7. {{end}}
  8. {{define "replies"}}
  9. {{if .}}
  10. <ul>
  11. {{range . }}
  12. <li class="post">
  13. <div class="postHead">
  14. <div class="postTitle"><b>{{.Title}}</b></div>
  15. </div>
  16. <div class="postBody">{{.Body}}</div>
  17. {{template "replies" .Replies}}
  18. </li>
  19. {{end}}
  20. </ul>
  21. {{end}}
  22. {{end}}

Playground 示例

英文:

To recurse down a hierarchy, use a named template that executes itself. In the following example, the template "replies" executes "replies" to display sub-replies:

  1. {{define &quot;main&quot;}}
  2. &lt;div id=&quot;post&quot;&gt;
  3. {{.Title}}
  4. {{.Body}}
  5. {{template &quot;replies&quot; .Replies}}
  6. &lt;/div&gt;
  7. {{end}}
  8. {{define &quot;replies&quot;}}
  9. {{if .}}
  10. &lt;ul&gt;
  11. {{range . }}
  12. &lt;li class=&quot;post&quot;&gt;
  13. &lt;div class=&quot;postHead&quot;&gt;
  14. &lt;div class=&quot;postTitle&quot;&gt;&lt;b&gt;{{.Title}}&lt;/b&gt;&lt;/div&gt;
  15. &lt;/div&gt;
  16. &lt;div class=&quot;postBody&quot;&gt;{{.Body}}&lt;/div&gt;
  17. {{template &quot;replies&quot; .Replies}}
  18. &lt;/li&gt;
  19. {{end}}
  20. &lt;/ul&gt;
  21. {{end}}
  22. {{end}}

Playground Example

答案2

得分: 4

你刚刚定义了一个递归数据类型。你可以通过定义一个递归模板来渲染它:

  1. {{define "replies"}}
  2. <ul>
  3. {{ range $key, $value := . }}
  4. <li class="post">
  5. <div class="postHead">
  6. <div class="postTitle"><b>{{ $value.ID }}</b></div>
  7. </div>
  8. <div class="postBody">{{ $value.PostNum }}</div>
  9. </li>
  10. {{template "replies" .Replies}}
  11. {{end}}
  12. </ul>
  13. {{end}}
  14. <div id="posts">
  15. {{ .Title }}
  16. {{ .Body }}
  17. {{ template "replies" .Replies }}
  18. </div>
英文:

You just have defined a recursive data type. You can render it by defining a recursive template:

  1. {{define &quot;replies&quot;}}
  2. &lt;ul&gt;
  3. {{ range $key, $value := . }}
  4. &lt;li class=&quot;post&quot;&gt;
  5. &lt;div class=&quot;postHead&quot;&gt;
  6. &lt;div class=&quot;postTitle&quot;&gt;&lt;b&gt;{{ $value.ID }}&lt;/b&gt;&lt;/div&gt;
  7. &lt;/div&gt;
  8. &lt;div class=&quot;postBody&quot;&gt;{{ $value.PostNum }}&lt;/div&gt;
  9. &lt;/li&gt;
  10. {{template &quot;replies&quot; .Replies}}
  11. {{end}}
  12. &lt;/ul&gt;
  13. {{end}}
  14. &lt;div id=&quot;posts&quot;&gt;
  15. {{ .Title }}
  16. {{ .Body }}
  17. {{ template &quot;replies&quot; .Replies }}
  18. &lt;/div&gt;

huangapple
  • 本文由 发表于 2017年2月22日 02:25:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/42375121.html
匿名

发表评论

匿名网友

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

确定