Introducción: ¿Por qué GraphQL y Go son la pareja ideal?
El desarrollo web moderno requiere APIs flexibles y de alto rendimiento. REST API, a pesar de su popularidad, a menudo sufre de sobrecarga de datos (over-fetching) o falta de datos (under-fetching). GraphQL resuelve este problema permitiendo al cliente solicitar exactamente lo que necesita. Y Go (Golang) con su velocidad, simplicidad y soporte incorporado para la concurrencia se convierte en el lenguaje ideal para crear servidores GraphQL.
En este tutorial, crearemos paso a paso una API GraphQL completa en Go. Aprenderás cómo configurar el servidor, definir el esquema, escribir resolvers, así como implementar consultas (queries) y mutaciones (mutations). Al final del artículo, tendrás una API funcional lista para integrarse con cualquier cliente.
Paso 1: Configuración del proyecto e instalación de dependencias
Para empezar, crearemos un nuevo módulo Go e instalaremos las bibliotecas necesarias. Usaremos dos bibliotecas GraphQL populares: graphql-go y graphql-go-handler.
1.1. Inicialización del módulo
go mod init graphql-tutorial1.2. Instalación de bibliotecas
go get github.com/graphql-go/graphqlgo get github.com/graphql-go/handlerEstas bibliotecas proporcionan todas las herramientas necesarias para trabajar con esquemas, tipos y resolvers.
Paso 2: Creación del esquema GraphQL básico
El esquema es el corazón de una API GraphQL. Define qué datos se pueden obtener y qué acciones se pueden realizar. Comenzaremos con un modelo simple de "Usuario".
2.1. Definición del tipo User
import "github.com/graphql-go/graphql"
var userType = graphql.NewObject(graphql.ObjectConfig{ Name: "User", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.Int, }, "name": &graphql.Field{ Type: graphql.String, }, "email": &graphql.Field{ Type: graphql.String, }, },})2.2. Creación de la consulta raíz
var rootQuery = graphql.NewObject(graphql.ObjectConfig{ Name: "RootQuery", Fields: graphql.Fields{ "user": &graphql.Field{ Type: userType, Args: graphql.FieldConfigArgument{ "id": &graphql.ArgumentConfig{ Type: graphql.Int, }, }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { id, _ := p.Args["id"].(int) // Aquí irá la lógica para obtener el usuario de la BD return getUserByID(id), nil }, }, },})2.3. Combinación en el esquema
var schema, _ = graphql.NewSchema(graphql.SchemaConfig{ Query: rootQuery,})Paso 3: Implementación de resolvers y servidor
Ahora que el esquema está listo, necesitamos escribir los resolvers: las funciones que realmente devuelven los datos. Para simplificar, usaremos un almacenamiento en memoria.
3.1. Almacenamiento en memoria
type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"`}
var users = []User{ {ID: 1, Name: "Iván Petrov", Email: "ivan@example.com"}, {ID: 2, Name: "María Sidorova", Email: "maria@example.com"},}
func getUserByID(id int) *User { for _, u := range users { if u.ID == id { return &u } } return nil}3.2. Inicio del servidor HTTP
package main
import ( "fmt" "log" "net/http"
"github.com/graphql-go/handler")
func main() { h := handler.New(&handler.Config{ Schema: &schema, Pretty: true, GraphiQL: true, // Habilitamos el IDE integrado })
http.Handle("/graphql", h) fmt.Println("Servidor iniciado en")