Ответ 1
Изменение: см. fooobar.com/questions/1233292/... для более актуального ответа.
Оригинальный ответ:
https://golang.org/pkg/text/template/#hdr-Variables:
Область действия переменной распространяется на действие "end" структуры управления ("if", "with" или "range"), в которой она объявлена, или до конца шаблона, если такой структуры управления нет.
Таким образом, $prev_year
вы определили с помощью {{$prev_year:=$year}}
действует только до... следующей строки ({{end}}
).
Кажется, нет способа обойти это.
"Правильный" способ сделать это - убрать эту логику из шаблона и выполнить группировку в коде Go.
Вот рабочий пример: https://play.golang.org/p/DZoSXo9WQR
package main
import (
"fmt"
"os"
"text/template"
"time"
)
type Tournament struct {
Place string
Date time.Time
}
type TournamentGroup struct {
Year int
Tournaments []Tournament
}
func groupTournamentsByYear(tournaments []Tournament) []TournamentGroup {
if len(tournaments) == 0 {
return nil
}
result := []TournamentGroup{
{
Year: tournaments[0].Date.Year(),
Tournaments: make([]Tournament, 0, 1),
},
}
i := 0
for _, tournament := range tournaments {
year := tournament.Date.Year()
if result[i].Year == year {
// Add to existing group
result[i].Tournaments = append(result[i].Tournaments, tournament)
} else {
// New group
result = append(result, TournamentGroup{
Year: year,
Tournaments: []Tournament{
tournament,
},
})
i++
}
}
return result
}
func main() {
tournaments := []Tournament{
// for clarity - date is sorted, we don't need sort it again
{"Town1", time.Date(2015, time.November, 10, 23, 0, 0, 0, time.Local)},
{"Town2", time.Date(2015, time.October, 10, 23, 0, 0, 0, time.Local)},
{"Town3", time.Date(2014, time.November, 10, 23, 0, 0, 0, time.Local)},
}
t, err := template.New("").Parse('
{{$prev_year:=0}}
{{range .}}
Actions in year {{.Year}}:
{{range .Tournaments}}
{{.Place}}, {{.Date}}
{{end}}
{{end}}
')
if err != nil {
panic(err)
}
err = t.Execute(os.Stdout, groupTournamentsByYear(tournaments))
if err != nil {
fmt.Println("executing template:", err)
}
}