Introduccion a Templ

Por: Artiko
templgotemplatesweb

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:

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:

  1. Escribes archivos .templ con la sintaxis de Templ
  2. Ejecutas templ generate que convierte cada .templ en un archivo .go
  3. 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