我正在尝试使用在 Go 模板范围循环外声明的变量来查看上一篇文章是否与当前文章发生在同一天。这是一个简化的示例。
其中 .Posts
是一个帖子结构数组,每个结构都有一个 .Content
和一个 .Date
。
{{ $prevDate := "" }}
{{ range $post := .Posts }}
{{ if ne $prevDate $post.Date }}
<div class="post-date">Posts dated: {{ $post.Date }}</div>
{{ end }}
<div class="post-content">{{ $post.Content }}</div>
{{ $prevDate := $post.Date }}
{{ end }}
问题是 $prevDate
似乎在每次循环迭代开始时重置为 ""
。
任何人都可以帮助我理解为什么每次迭代都会重置 $prevDate
的值,并且可能会建议一种方法来完成我在这里尝试做的事情吗?
最佳答案
注意: Go 1.11 will support modifying template variables via assignment .这将是有效代码:
{{ $v := "init" }}
{{ if true }}
{{ $v = "changed" }}
{{ end }}
v: {{ $v }} {{/* "changed" */}}
Go 1.11 之前的原始答案如下:
变量不会被重置。基本上,您在循环内重新声明了 $prevDate
变量。但它仅在重新声明之后和 {{range}}
的结束 {{end}}
标记之前的范围内。因此,当循环的下一次迭代到来时,您只会看到您没有更改的“外部”变量(因为您创建了一个新变量)。
您不能更改您创建的模板变量的值。
例如,您可以使用以下 range
形式:
{{ range $index, $post := .Posts }}
还有……
解决方案#1:注册函数
您可以为模板注册一个函数(参见 template.Funcs()
),您可以将 $index
传递给该函数,它将返回前一个元素的日期字段(在 $索引 -1
).
它看起来像这样:
func PrevDate(i int) string {
if i == 0 {
return ""
}
return posts[i-1].Date
}
// Registering it:
var yourTempl = template.Must(template.New("").
Funcs(map[string]interface{}{"PrevDate": PrevDate}).
Parse(yourStringTemplate))
在您的模板中,您可以这样调用它:
{{range $index, $post := .Posts}}
{{$prevDate := PrevDate $index}}
{{end}}
解决方案#2:使用帖子方法
这个解决方案是模拟的,但更简单:在您的 Posts
中添加一个方法,您可以直接调用它。无需注册函数。
例如:
type Post struct {
// Your Post type
Date string
}
type Posts []Post
func (p *Posts) PrevDate(i int) string {
if i == 0 {
return ""
}
return (*p)[i-1].Date
}
在您的模板中,您可以这样调用它:
{{range $index, $post := .Posts}}
{{$prevDate := $.Posts.PrevDate $index}}
{{end}}
关于go - 在 Go 模板范围循环中,是否在每次迭代时重置循环外声明的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41163354/