En esta página
Proyecto final: gestor de tareas CLI con API HTTP
Proyecto final: gestor de tareas CLI con API HTTP
¡Enhorabuena por llegar al proyecto final! Has recorrido todo el ecosistema esencial de Go: tipos, funciones, structs, interfaces, goroutines, channels, manejo de errores, módulos y HTTP. Ahora vas a integrar todo ese conocimiento construyendo un proyecto real y completo.
¿Qué construirás?
Un gestor de tareas que funciona de dos modos:
- Modo CLI: interactúas desde la línea de comandos (
listar,crear,completar,eliminar) - Modo servidor HTTP: expone una API REST en
localhost:8080
Los datos se persisten en un archivo JSON, la concurrencia está protegida con sync.RWMutex, y el servidor se cierra con gracia capturando señales del sistema operativo.
Arquitectura del proyecto
tareas-go/
├── go.mod
└── main.go ← todo en un archivo para este proyectoEl diseño sigue estos principios de Go:
- Interfaz
Repositorio: desacopla la lógica de negocio de la implementación de almacenamiento - Struct
RepoJSON: implementación concreta con persistencia en archivo - Concurrencia segura:
sync.RWMutexprotege el mapa de tareas - Graceful shutdown: el servidor HTTP escucha señales del OS para cerrarse limpiamente
- Error handling explícito: cada función retorna
error; los errores centinela permiten comparación conerrors.Is
Conceptos aplicados
1. Interfaces para desacoplamiento
La interfaz Repositorio define el contrato que cualquier implementación de almacenamiento debe cumplir. El CLI y el servidor trabajan exclusivamente con esta interfaz:
type Repositorio interface {
Crear(título, descripción string, prioridad int) (*Tarea, error)
Listar() ([]*Tarea, error)
ObtenerPorID(id int) (*Tarea, error)
Actualizar(tarea *Tarea) error
Eliminar(id int) error
}Para agregar almacenamiento en PostgreSQL, solo necesitarías crear una RepoPostgres struct que implemente los mismos 5 métodos.
2. Concurrencia con sync.RWMutex
El servidor HTTP recibe múltiples requests concurrentes. El mapa de tareas debe protegerse:
// Múltiples lecturas concurrentes están permitidas
func (r *RepoJSON) Listar() ([]*Tarea, error) {
r.mu.RLock() // múltiples goroutines pueden leer simultáneamente
defer r.mu.RUnlock()
// ...
}
// Solo una escritura a la vez
func (r *RepoJSON) Crear(...) (*Tarea, error) {
r.mu.Lock() // bloquea TODO: lectores y escritores
defer r.mu.Unlock()
// ...
}3. Pattern matching de ServeMux (Go 1.22+)
mux.HandleFunc("GET /api/tareas", listar)
mux.HandleFunc("POST /api/tareas", crear)
mux.HandleFunc("GET /api/tareas/{id}", obtenerPorID)
mux.HandleFunc("DELETE /api/tareas/{id}", eliminar)El método HTTP en el patrón garantiza que GET /api/tareas y POST /api/tareas van a handlers diferentes automáticamente.
4. Graceful shutdown con channels y select
señales := make(chan os.Signal, 1)
signal.Notify(señales, os.Interrupt, syscall.SIGTERM)
errCh := make(chan error, 1)
go func() {
errCh <- srv.ListenAndServe()
}()
select {
case err := <-errCh:
// El servidor terminó por error
case <-señales:
// Ctrl+C o SIGTERM: cerrar con gracia
srv.Shutdown(ctx)
}Cómo ejecutar el proyecto
# Inicializar el módulo
go mod init github.com/tuusuario/tareas-go
# Listar tareas
go run main.go listar
# Crear una tarea
go run main.go crear --titulo "Estudiar Go" --desc "Completar el curso" --prioridad 3
# Completar una tarea
go run main.go completar 1
# Iniciar el servidor HTTP
go run main.go servidor
# En otra terminal, probar la API
curl http://localhost:8080/api/tareas
curl -X POST http://localhost:8080/api/tareas \
-H "Content-Type: application/json" \
-d '{"titulo":"Nueva tarea","prioridad":2}'
curl http://localhost:8080/api/tareas/1
curl -X DELETE http://localhost:8080/api/tareas/1Extensiones posibles
Una vez que el proyecto base funcione, puedes extenderlo con:
- Filtros en el listado:
GET /api/tareas?estado=pendiente&prioridad=3 - Autenticación básica: middleware que verifica un API key en el header
- Paginación:
GET /api/tareas?pagina=2&por_pagina=10 - Fechas de vencimiento: campo
VenceEn *time.TimeenTarea - Notificaciones: goroutine que verifica tareas vencidas y las notifica
- SQLite: implementar
RepoSQLitecondatabase/sqly el drivermodernc.org/sqlite - Tests:
RepoEnMemoriapara pruebas unitarias sin archivos
Lo que aprendiste en este curso
Con este proyecto completas tu dominio de Go esencial:
- Sistema de tipos estático, fuerte y expresivo
- Funciones con múltiples retornos y el patrón
(valor, error) - Structs, métodos e interfaces implícitas
- Slices y maps con sus idioms específicos
- Punteros seguros sin aritmética de punteros
- Manejo de errores explícito con
errors.Isyerrors.As - Goroutines — millones posibles con 2-4 KB cada una
- Channels para comunicación segura entre goroutines
- Patrones de concurrencia: worker pool, fan-in/out, pipeline
context.Contextpara cancelación propagada- Sistema de módulos y paquetes
- API REST con
net/httpyServeMuxde Go 1.22+
Go es el lenguaje de la infraestructura moderna. Docker, Kubernetes, Terraform, Prometheus — todos nacieron en Go. Con este curso tienes las bases para construir herramientas de la misma calidad.
El siguiente paso natural es explorar el ecosystem de Go: gorm o sqlx para bases de datos, gin o chi para routing avanzado, y testify para pruebas más expresivas.
Inicia sesión para guardar tu progreso