Introduccion a Templ
Capitulo 5: Introduccion a Templ
Templ es un motor de templates para Go que genera codigo Go puro a partir de archivos .templ. A diferencia de html/template de la libreria estandar, Templ ofrece tipado estatico, autocompletado en el editor y deteccion de errores en tiempo de compilacion.
Por que no usar html/template
La libreria estandar html/template tiene limitaciones que se vuelven problematicas en proyectos reales:
- Sin verificacion de tipos: los datos se pasan como
interface{}, los errores aparecen en runtime - Sin autocompletado: el editor no puede ayudarte dentro de los templates
- Sintaxis limitada: la logica compleja requiere funciones personalizadas registradas manualmente
- Sin composicion real: incluir templates dentro de otros es fragil y propenso a errores
Templ resuelve todo esto generando funciones Go reales que el compilador verifica.
Instalar Templ
# Instalar la herramienta CLI de templ
go install github.com/a-h/templ/cmd/templ@latest
# Verificar la instalacion
templ version
Para desarrollo, es recomendable instalar tambien el plugin de tu editor. En VS Code busca la extension templ-vscode.
El flujo de trabajo
El flujo con Templ sigue estos pasos:
- Escribes archivos
.templcon la sintaxis de Templ - Ejecutas
templ generateque convierte cada.templen un archivo.go - Compilas tu proyecto Go normalmente con
go build
# Generar codigo Go a partir de los .templ
templ generate
# O en modo watch para desarrollo
templ generate --watch
Sintaxis basica de archivos .templ
Un archivo .templ se parece mucho a Go mezclado con HTML. Cada archivo pertenece a un package y define componentes como funciones:
package components
templ Hello() {
<div>
<h1>Hola desde Templ</h1>
<p>Este es mi primer componente.</p>
</div>
}
Al ejecutar templ generate, este archivo produce un hello_templ.go con una funcion Hello() que retorna un templ.Component.
Componente con parametros tipados
Los componentes reciben parametros con tipos de Go:
package components
templ Greeting(name string) {
<div class="greeting">
<h1>Hola, { name }!</h1>
<p>Bienvenido al sistema.</p>
</div>
}
Puedes usar cualquier tipo de Go como parametro:
package components
type User struct {
Name string
Email string
Admin bool
}
templ UserCard(user User) {
<div class="card">
<h2>{ user.Name }</h2>
<p>{ user.Email }</p>
</div>
}
Si pasas un tipo incorrecto, el compilador de Go lo detecta antes de ejecutar.
Expresiones Go dentro de templates
Puedes insertar cualquier expresion Go que retorne un string usando llaves:
package components
import "fmt"
import "strings"
templ Stats(count int, items []string) {
<div>
<p>Total: { fmt.Sprintf("%d", count) }</p>
<p>Items: { strings.Join(items, ", ") }</p>
</div>
}
Para valores que no son strings, usa fmt.Sprintf o funciones de conversion.
Condicionales con @if
La directiva @if permite renderizado condicional:
package components
templ UserBadge(name string, isAdmin bool) {
<div class="badge">
<span>{ name }</span>
if isAdmin {
<span class="admin">Administrador</span>
} else {
<span class="user">Usuario</span>
}
</div>
}
Nota que en Templ se usa if directamente (sin @), como en Go normal pero dentro del contexto del template.
Bucles con @for
Iterar sobre slices funciona igual que en Go:
package components
templ TaskList(tasks []string) {
<ul class="tasks">
for _, task := range tasks {
<li>{ task }</li>
}
</ul>
}
Con indices:
package components
import "fmt"
templ NumberedList(items []string) {
<ol>
for i, item := range items {
<li>{ fmt.Sprintf("%d. %s", i+1, item) }</li>
}
</ol>
}
Renderizar desde un handler Go
Para usar un componente Templ en un handler HTTP, llamas al metodo Render:
package main
import (
"net/http"
"myapp/components"
)
func handleHome(w http.ResponseWriter, r *http.Request) {
component := components.Greeting("Mundo")
component.Render(r.Context(), w)
}
func main() {
http.HandleFunc("/", handleHome)
http.ListenAndServe(":8080", nil)
}
El componente escribe el HTML directamente al http.ResponseWriter.
templ.Handler() para servir componentes directamente
Si tu componente no necesita logica adicional, puedes servirlo directamente como handler:
package main
import (
"net/http"
"myapp/components"
)
func main() {
// Servir un componente directamente como handler HTTP
http.Handle("/hello", templ.Handler(components.Hello()))
// Con parametros
http.Handle("/welcome", templ.Handler(
components.Greeting("visitante"),
))
http.ListenAndServe(":8080", nil)
}
templ.Handler() envuelve el componente en un http.Handler que maneja el content-type y el renderizado automaticamente.
Resumen del flujo completo
# 1. Crear archivo .templ
# components/hello.templ
# 2. Generar codigo Go
templ generate
# 3. Esto crea components/hello_templ.go
# con funciones Go tipadas
# 4. Compilar y ejecutar
go run .
El ciclo es simple: editas .templ, generas .go, compilas. En desarrollo, templ generate --watch automatiza el paso 2.
Estructura de archivos resultante
proyecto/
├── main.go
├── go.mod
├── go.sum
└── components/
├── hello.templ # Tu codigo fuente
├── hello_templ.go # Generado por templ (no editar)
├── greeting.templ
└── greeting_templ.go # Generado por templ (no editar)
Los archivos *_templ.go son generados y no deben editarse manualmente. Es buena practica agregarlos al .gitignore o regenerarlos en CI.
Anterior: Servir archivos estaticos y middleware | Siguiente: Templ Avanzado