Note: Go 1.11 will support modifying template variables via assignment. This will be valid code:
{{ $v := "init" }}
{{ if true }}
{{ $v = "changed" }}
{{ end }}
v: {{ $v }} {{/* "changed" */}}
Original answer pre-dating Go 1.11 follows:
Variables are not reset. Basically what happens is that you redeclare the $prevDate
variable inside the loop. But it is only in scope after the redeclaration and before the closing {{end}}
tag of the {{range}}
. So when the next iteraiton of the loop comes, you only see the “outer” variable which you haven’t changed (because you created a new).
You can’t change the values of the template variables you create.
What you can do is for example use the following range
form:
{{ range $index, $post := .Posts }}
And…
Solution #1: with a registered Function
And you can register a function for the template (see template.Funcs()
) to which you can pass the $index
and it would return the date field of the previous element (at $index -1
).
It would look something like this:
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))
And from your template you can call it like:
{{range $index, $post := .Posts}}
{{$prevDate := PrevDate $index}}
{{end}}
Solution #2: with a Method of Posts
This solution is analog but is even simpler: add a method to your Posts
and you can call it directly. No need to register a function.
For example:
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
}
And from your template you can call it like:
{{range $index, $post := .Posts}}
{{$prevDate := $.Posts.PrevDate $index}}
{{end}}