Saltar al contenido

Variables dentro de plantillas en golang

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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *