Go by Example: Text Templates

Go ofrece soporte integrado para crear contenido dinámico o mostrar salidas personalizadas al usuario con el paquete text/template. Un paquete hermano llamado html/template proporciona la misma API pero tiene características de seguridad adicionales y debe ser utilizado para generar HTML.

package main
import (
    "os"
    "text/template"
)
func main() {

Podemos crear una nueva plantilla y analizar su cuerpo desde una cadena. Las plantillas son una mezcla de texto estático y “acciones” encerradas en {{...}} que se utilizan para insertar contenido dinámicamente.

    t1 := template.New("t1")
    t1, err := t1.Parse("Value is {{.}}\n")
    if err != nil {
        panic(err)
    }

Alternativamente, podemos usar la función template.Must para generar un pánico en caso de que Parse devuelva un error. Esto es especialmente útil para plantillas inicializadas en el ámbito global.

    t1 = template.Must(t1.Parse("Value: {{.}}\n"))

Al “ejecutar” la plantilla generamos su texto con valores específicos para sus acciones. La acción {{.}} es reemplazada por el valor pasado como parámetro a Execute.

    t1.Execute(os.Stdout, "some text")
    t1.Execute(os.Stdout, 5)
    t1.Execute(os.Stdout, []string{
        "Go",
        "Rust",
        "C++",
        "C#",
    })

Función auxiliar que usaremos a continuación.

    Create := func(name, t string) *template.Template {
        return template.Must(template.New(name).Parse(t))
    }

Si los datos son una estructura, podemos usar la acción {{.FieldName}} para acceder a sus campos. Los campos deben ser exportados para ser accesibles cuando una plantilla se está ejecutando.

    t2 := Create("t2", "Name: {{.Name}}\n")
    t2.Execute(os.Stdout, struct {
        Name string
    }{"Jane Doe"})

Lo mismo se aplica a los mapas; con los mapas no hay restricción en el caso de los nombres de las claves.

    t2.Execute(os.Stdout, map[string]string{
        "Name": "Mickey Mouse",
    })

if/else proporciona ejecución condicional para plantillas. Un valor se considera falso si es el valor predeterminado de un tipo, como 0, una cadena vacía, un puntero nulo, etc. Este ejemplo demuestra otra característica de las plantillas: usar - en acciones para recortar espacios en blanco.

    t3 := Create("t3",
        "{{if . -}} yes {{else -}} no {{end}}\n")
    t3.Execute(os.Stdout, "not empty")
    t3.Execute(os.Stdout, "")

Los bloques range nos permiten recorrer slices, arrays, mapas o canales. Dentro del bloque range {{.}} se establece en el elemento actual de la iteración.

    t4 := Create("t4",
        "Range: {{range .}}{{.}} {{end}}\n")
    t4.Execute(os.Stdout,
        []string{
            "Go",
            "Rust",
            "C++",
            "C#",
        })
}
$ go run templates.go 
Value: some text
Value: 5
Value: [Go Rust C++ C#]
Name: Jane Doe
Name: Mickey Mouse
yes 
no 
Range: Go Rust C++ C# 

Siguiente ejemplo: Regular Expressions.