Alexa, miembro de este equipo, nos ha hecho el favor de escribir esta reseña ya que domina a la perfección el tema.
Solución:
Editar: consulte https://stackoverflow.com/a/52925780/1685538 para obtener una respuesta más actualizada.
Respuesta original:
https://golang.org/pkg/text/template/#hdr-Variables:
El ámbito de una variable se extiende hasta la acción “final” de la estructura de control (“si”, “con” o “rango”) en la que se declara, o hasta el final de la plantilla si no existe tal estructura de control.
Entonces el $prev_year
tu defines con $prev_year:=$year
solo vive hasta .. la siguiente línea (end
).
Parece que no hay forma de evitar eso.
La forma “correcta” de hacer esto es sacar esa lógica de su plantilla y agrupar en su código Go.
Aquí hay un ejemplo práctico: 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)
En go1.11, text/template y, por lo tanto, html/template pudieron establecer el valor de las variables existentes, lo que significa que se puede hacer que el código original funcione con una modificación muy pequeña.
Cambiar
$prev_year:=$year
Para
$prev_year = $year
Patio de recreo
Como se menciona en esta respuesta, el alcance de esa variable “reasignación” termina con el end
cuadra. Por lo tanto, usando variables estándar solamente no hay forma de evitar el problema y debe resolverse dentro del programa Go ejecutando la plantilla.
Sin embargo, en algunos marcos esto no es tan fácil (por ejemplo, protoc-gen-gotemplate).
La biblioteca Sprig agrega funcionalidad adicional al lenguaje de plantilla estándar. Uno de ellos son los mapas mutables que se pueden utilizar de la siguiente manera:
// init the dictionary (you can init it without initial key/values as well)
$myVar := dict "key" "value"
// getting the "key" from the dictionary (returns array) and then fetching the first element from that array
first
// conditional update block
if eq "some" "some"
// the $_ seems necessary because Go template functions need to return something
$_ := set $myVar "key" "newValue"
end
// print out the updated value
first
Este pequeño ejemplo se imprime:
value
newValue
Un enfoque pragmático sería usar un solo diccionario para todas las variables mutables y almacenarlas bajo su nombre de variable correspondiente como key.
Referencia:
- http://masterminds.github.io/sprig/dicts.html
- https://github.com/Masterminds/sprig
valoraciones y comentarios
Si crees que te ha sido útil este artículo, sería de mucha ayuda si lo compartes con más desarrolladores de esta manera contrubuyes a dar difusión a nuestro contenido.