Uso de GraphQL con Go: tutorial básico
¡Bienvenidos compatriotas de golang! En este tutorial, veremos cómo interactuar con un servidor GraphQL en un programa basado en Go. Al final de este tutorial, deberíamos saber cómo hacer lo siguiente:
En este tutorial, nos centraremos en aprender el aspecto de recuperación de datos de GraphQL y usaremos una fuente de datos en memoria para apoyarlo. Esto debería darnos una buena base sobre la que desarrollarnos en tutoriales posteriores.
Bien, antes de sumergirnos, deberíamos comprender realmente los conceptos básicos de GraphQL. Como desarrolladores, ¿cuáles son los beneficios de usarlo?
Bueno, considere un sistema que maneja cientos de miles o incluso millones de solicitudes por día. Tradicionalmente, usaríamos una API del sistema que se encuentra frente a una base de datos, que devuelve una respuesta JSON grande con mucha información redundante que no necesariamente necesitamos.
Si estamos ante una aplicación a gran escala, enviar datos redundantes puede resultar costoso y obstruir el ancho de banda de nuestra red debido al tamaño de la carga útil.
GraphQL básicamente nos permite reducir el ruido y describir los datos que queremos recuperar de nuestra API para que solo los necesitemos para nuestra tarea/vista/lo que sea actual.
Este es sólo un ejemplo de los múltiples beneficios que nos ofrece esta tecnología. Con suerte, veremos más de estos beneficios con anticipación en la próxima serie de tutoriales.
Una cosa importante a tener en cuenta es que GraphQL no es un lenguaje de consulta como nuestro SQL tradicional. Es una abstracción que se encuentra frente a nuestra API y no está vinculada a ninguna base de datos o motor de almacenamiento específico.
Esto es realmente genial. Podemos configurar un servidor GraphQL que interactúe con un proveedor existente y luego construir alrededor de este nuevo servidor GraphQL sin tener que preocuparnos por modificar la API REST existente.
Veamos en qué se diferencian los enfoques RESTful de los enfoques GraphQL. Ahora, digamos que estamos creando un servicio que devuelve todos los tutoriales del sitio. Si queremos información para un tutorial específico, normalmente creamos un punto final API que nos permite recuperar un tutorial específico según su ID:
<. p> Si se le da una identificación válida, devolverá una respuesta similar a esta:Ahora, digamos que queremos crear un widget que enumere 5 publicaciones sobre libros escritos por este autor. Podemos presionar el punto final /author/:id para recuperar todas las publicaciones escritas por ese autor y luego realizar llamadas posteriores para recuperar cada una de las primeras 5 publicaciones. Alternativamente, podemos crear un punto final completamente nuevo que nos devuelva estos datos.
Ninguna solución parece particularmente atractiva, ya que crearían una cantidad innecesaria de solicitudes o devolverían demasiados datos, lo que resalta dónde el enfoque RESTful comienza a mostrar algunas grietas.
Aquí es donde entra en juego GraphQL. Usando GraphQL podemos definir la estructura exacta de los datos que queremos que se devuelvan en una consulta. Entonces, si quisiéramos la información anterior, podríamos crear una consulta que se vería así:
Esto nos devolvería nuestro tutorial, el autor de ese tutorial y un conjunto de tutoriales que representan los tutoriales escritos por ese ID de autor sin tener que enviar x solicitudes REST adicionales para obtener la información. ¿Qué tan bueno es eso?
Bien, ahora que sabemos un poco más sobre GraphQL y para qué podemos usarlo, veámoslo en la práctica.
Crearemos un servidor GraphQL simple en Go usando la implementación graphql-go/graphql.
Primero inicialicemos nuestro proyecto usando go mod init:
A continuación, creemos un proyecto llamado main.go. Comenzaremos de manera simple creando un servidor GraphQL muy simple, que tiene. un solucionador muy simple:
Ahora, veamos qué sucede si intentamos ejecutarlo:
Entonces, si todo funciona bien, entonces podemos configurar un servidor GraphQL muy simple. y realizar consultas muy simples en este servidor.
Analicemos lo que sucede en el código anterior para que podamos extenderlo más. En las líneas 14-21 definimos nuestro esquema. Cuando realizamos una consulta en nuestra API GraphQL, básicamente definimos qué campos del objeto queremos que se nos devuelvan, por lo que tenemos que redefinirlos en nuestro campo Esquema.
En la línea 17 anterior, definimos una función de analizador que se activará cada vez que el campo solicite este contenido específico. Por ahora, solo devolvemos la cadena "mundo", pero implementaremos la capacidad de consultar la base de datos desde aquí.
Echemos un vistazo a la segunda parte del archivo main.go. En la línea 30 comenzamos a definir el campo de solicitud de consulta hola.
Luego creamos una estructura de parámetros que contiene una referencia al esquema que definimos, así como a nuestra solicitud RequestString.
Finalmente, en la línea 36 ejecutamos la solicitud y completamos r con el resultado de la solicitud. Luego manejamos algunos errores y luego organizamos la respuesta en JSON y la imprimimos en nuestra consola.
Ahora que tenemos un servidor GraphQL muy simple en funcionamiento y que podemos consultarlo, vayamos un paso más allá y construyamos un ejemplo más complejo.
Crearemos un servidor GraphQL que devuelva una lista en memoria de tutoriales y sus autores, así como cualquier comentario para esos tutoriales específicos.
Definamos algunas estructuras que representan un Tutorial, un Autor y un Comentario:
Luego podemos crear una función populate() muy simple que devolverá una matriz de tipo Tutorial:
Esto nos dará una lista simple de tutoriales que luego podremos abordar más adelante.
Comenzaremos creando un nuevo objeto en GraphQL usando Graphql.NewObject(). Usaremos la tipificación estricta de GraphQL para definir 3 tipos diferentes que coincidirán con las 3 estructuras que ya hemos definido.
Nuestra estructura Commentstruct es posiblemente la más simple, solo contiene una cadena Body, por lo que podemos representarla fácilmente como commentType:
A continuación, nos ocuparemos de la estructura Author y la definiremos como un nuevo graphql.NewObject(). Esto es un poco más complicado porque tiene un campo String y una lista de valores Int que representan los ID de los tutoriales que escribieron.
Finalmente, definamos nuestro tipo de tutorial que encapsulará un autor y una serie de comentarios, así como una ID y un título:
Ahora que tenemos nuestro sistema de tipos definido, comencemos. actualizándolo Nuestro esquema refleja estos nuevos tipos. Definiremos 2 campos distintos, el primero será nuestro campo de tutorial que permitirá a nuestros Tutoriales recuperar personas según el ID de la consulta entrante. El segundo será un campo de lista que nos permitirá recuperar la gama completa de Tutoriales que hemos definido en la memoria.
Así que creamos nuestros tipos y actualizamos nuestro esquema GraphQL, ¡y lo estamos haciendo bastante bien!
Probemos nuestro nuevo servidor GraphQL y procesemos nuestras consultas enviadas. Intentemos cambiar la consulta a nuestro esquema de lista, que ya tenemos en nuestra función main():
Vamos a desglosarlo. Entonces, en nuestra consulta, tenemos un objeto raíz especial. Luego decimos que queremos los campos en ese objeto de lista. En la lista devuelta, esperamos ver la identificación, el título, los comentarios y el autor.
Cuando ejecutamos esto, deberíamos ver el siguiente resultado:
Como podemos ver, nuestra consulta devuelve todos nuestros tutoriales en formato JSON, que se parece mucho a la estructura de nuestra consulta inicial.
Ahora intentemos consultar nuestro esquema de tutorial:
Una vez más, cuando ejecutemos esto, deberíamos ver que ha recuperado exitosamente los tutoriales individuales en la memoria ID=1:
Perfecto, parece que tenemos una lista de nuestro esquema de tutorial y nuestro esquema funciona como se esperaba.
Eso es todo lo que cubriremos en este tutorial inicial. Hemos configurado con éxito un servidor GraphQL simple respaldado por un almacén de datos en memoria.
En el próximo tutorial veremos las mutaciones de GraphQL y cambiaremos nuestra fuente de datos para usar una base de datos SQL