Introducción: Por qué GraphQL y Go son la pareja ideal
\nEn el desarrollo web moderno, GraphQL se ha convertido en el estándar para crear API flexibles y eficientes. En combinación con el lenguaje Go (Golang), conocido por su rendimiento y simplicidad, obtiene una herramienta poderosa para el desarrollo backend. En este tutorial paso a paso, crearemos una API GraphQL completa en Go desde cero, utilizando la popular biblioteca gqlgen.
Aprenderá a configurar el proyecto, definir el esquema, implementar resolvers y agregar middleware para autenticación. Al final del artículo, tendrá una API funcional lista para integrarse con cualquier frontend.
\n\n1. Configuración del proyecto e instalación de dependencias
\nPrimero, crearemos un nuevo módulo Go e instalaremos los paquetes necesarios. Asegúrese de tener instalado Go versión 1.18 o superior.
\nmkdir graphql-go-tutorial\ncd graphql-go-tutorial\ngo mod init graphql-go-tutorial\ngo get github.com/99designs/gqlgen@latest\ngo get github.com/99designs/gqlgen/graphql/introspection@latest\nAhora inicializamos gqlgen en el proyecto. Este comando creará la estructura básica de archivos:
go run github.com/99designs/gqlgen init\nDespués de la ejecución, verá la siguiente estructura:
\n- \n
graph/— directorio con archivos de esquema y resolvers \ngraph/schema.graphqls— definición del esquema GraphQL \ngraph/resolver.go— plantillas para los resolvers \nserver.go— punto de entrada de la aplicación \ngqlgen.yml— configuración del generador \n
2. Definición del esquema GraphQL
\nAbriremos el archivo graph/schema.graphqls y definiremos nuestro modelo de datos. Como ejemplo, crearemos un sistema simple de gestión de tareas (Task Manager):
type Task {\n id: ID!\n title: String!\n description: String\n status: TaskStatus!\n createdAt: Time!\n}\n\nenum TaskStatus {\n TODO\n IN_PROGRESS\n DONE\n}\n\ntype Query {\n tasks(status: TaskStatus): [Task!]!\n task(id: ID!): Task\n}\n\ntype Mutation {\n createTask(title: String!, description: String): Task!\n updateTask(id: ID!, title: String, description: String, status: TaskStatus): Task!\n deleteTask(id: ID!): Boolean!\n}\n\nscalar Time\nDespués de guardar el esquema, ejecutaremos la generación de código:
\ngo run github.com/99designs/gqlgen generate\nEste comando creará los archivos graph/model/models_gen.go con las estructuras Go y actualizará los resolvers.
3. Implementación de resolvers y lógica de negocio
\nAhora implementaremos la lógica en el archivo graph/schema.resolvers.go. Primero, crearemos un almacenamiento simple en memoria (in-memory store):
// En graph/resolver.go agregamos el almacenamiento\ntype Resolver struct {\n tasks []*model.Task\n mu sync.Mutex\n}\n\nfunc NewResolver() *Resolver {\n return &Resolver{\n tasks: make([]*model.Task, 0),\n }\n}\nAhora implementamos los resolvers para Query y Mutation:
\n// Query.Task\nfunc (r *queryResolver) Task(ctx context.Context, id string) (*model.Task, error) {\n r.mu.Lock()\n defer r.mu.Unlock()\n \n for _, task := range r.tasks {\n if task.ID == id {\n return task, nil\n }\n }\n return nil, fmt.Errorf("task not found")\n}\n\n// Mutation.CreateTask\nfunc (r *mutationResolver) CreateTask(ctx context.Context, title string, description *string) (*model.Task, error) {\n r.mu.Lock()\n defer r.mu.Unlock()\n \n task := &model.Task{\n ID: uuid.New().String(),\n Title: title,\n Description: description,\n Status: model.TaskStatusTodo,\n CreatedAt: time.Now(),\n }\n \n r.tasks = append(r.tasks, task)\n return task, nil\n}\n\n// Mutation.UpdateTask\nfunc (r *mutationResolver) UpdateTask(ctx context.Context, id string, title *string, description *string, status *model.TaskStatus) (*model.Task, error) {\n r.mu.Lock()\n defer r.mu.Unlock()\n \n for _, task