
Bonjour à tous! Il y a beaucoup d'articles sur GraphQL sur Habr, mais après les avoir parcourus, j'ai trouvé qu'ils contournaient tous un langage aussi merveilleux que Go. Aujourd'hui, je vais essayer de corriger ce malentendu. Pour ce faire, nous allons écrire une API sur Go à l'aide de GraphQL.
En bref: GraphQL est un langage de requête pour construire une API qui décrit sous quelle forme demander et renvoyer des données (des informations plus détaillées sur la ressource officielle graphql.imtqy.com et sur le hub )
Vous pouvez affirmer que GraphQL ou REST est mieux ici.
Nous aurons l'API classique: CRUD (créer, lire, mettre à jour, supprimer) ajouter, recevoir, modifier et supprimer des produits dans la boutique en ligne.
Côté serveur, nous utiliserons l'implémentation prête de GraphQL graphql-go
Vous devez d'abord télécharger graphql-go, cela peut être fait avec la commande
go get github.com/graphql-go/graphql
Ensuite, nous décrivons la structure du produit (sous forme simplifiée)
type Product struct { ID int64 `json:"id"` Name string `json:"name"` Info string `json:"info,omitempty"` Price float64 `json:"price"` }
ID
- identifiant unique, Name
- nom, Info
- informations sur le produit, Price
- prix
La première chose à faire est d'appeler la méthode Do
, qui accepte un schéma de données et des paramètres de requête comme paramètres d'entrée. Et il nous renverra les données résultantes (pour une transmission ultérieure au client)
result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, })
Code complet func executeQuery(query string, schema graphql.Schema) *graphql.Result { result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, }) if len(result.Errors) > 0 { fmt.Printf("errors: %v", result.Errors) } return result } func main() { http.HandleFunc("/product", func(w http.ResponseWriter, r *http.Request) { result := executeQuery(r.URL.Query().Get("query"), schema) json.NewEncoder(w).Encode(result) }) http.ListenAndServe(":8080", nil) }
Schema
- schéma de données, RequestString
- valeur du paramètre de chaîne de requête, dans notre cas, valeur de query
Schéma
Un schéma accepte deux types de données racine: Query
- données immuables, Mutation
- données mutables
var schema, _ = graphql.NewSchema( graphql.SchemaConfig{ Query: queryType, Mutation: mutationType, }, )
Requête
Query
est utilisée pour lire (et uniquement lire) les données. À l'aide de Query
nous spécifions les données que le serveur doit retourner.
Nous allons écrire une implémentation du type de données Query
, dans notre cas, elle contiendra des champs avec des informations sur un seul produit (produit) et une liste de marchandises (liste)
var queryType = graphql.NewObject( graphql.ObjectConfig{ Name: "Query", Fields: graphql.Fields{ "product": &graphql.Field{ Type: productType, Description: "Get product by id",
Le type queryType contient le Name
et les Fields
requis, ainsi que la Description
facultative (utilisée pour la documentation)
À son tour, le champ Fields
contient également le champ Type
requis et les Args
optionnels Args
, Resolve
et Description
Args (arguments)
Arguments - une liste de paramètres transférés du client au serveur et affectant le résultat des données renvoyées. Les arguments sont liés à un champ spécifique. Et les arguments peuvent être passés à la fois dans Query
et Mutation
.
?query={product(id:1){name,info,price}}
Dans ce cas, l'argument id
du champ product
avec une valeur de 1 indique qu'il est nécessaire de renvoyer le produit avec l'identifiant spécifié.
Pour la list
arguments sont omis, mais dans une application réelle, cela peut être, par exemple: limit
et offset
.
Résoudre (reconnaissance)
Toute la logique de travail avec les données (par exemple, les requêtes de base de données, le traitement et le filtrage) est dans les reconnaisseurs, ce sont eux qui renvoient les données qui seront transmises au client en réponse à la requête.
Tapez
GraphQL utilise son système de types pour décrire les données. Vous pouvez utiliser les types de base String
, Int
, Float
, Boolean
et les vôtres (personnalisés). Pour notre exemple, nous aurons besoin d'un Product
type personnalisé, qui décrira toutes les propriétés du produit
var productType = graphql.NewObject( graphql.ObjectConfig{ Name: "Product", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.Int, }, "name": &graphql.Field{ Type: graphql.String, }, "info": &graphql.Field{ Type: graphql.String, }, "price": &graphql.Field{ Type: graphql.Float, }, }, }, )
Pour chaque champ, le type de base est spécifié, dans ce cas graphql.Int
, graphql.String
, graphql.Float
.
Le nombre de champs imbriqués n'est pas limité, vous pouvez donc implémenter un système graphique de n'importe quel niveau.
Mutation
Les mutations sont ces données mutables, qui comprennent: l'ajout, l'édition et la suppression. Sinon, les mutations sont très similaires aux requêtes régulières: elles prennent également des arguments Args
et renvoient des données Resolve
en réponse à la requête.
Écrivons des mutations pour nos produits. var mutationType = graphql.NewObject(graphql.ObjectConfig{ Name: "Mutation", Fields: graphql.Fields{ "create": &graphql.Field{ Type: productType, Description: "Create new product", Args: graphql.FieldConfigArgument{ "name": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String),
Tous similaires à queryType
. Il n'y a qu'un seul petit type d' graphql.NewNonNull(graphql.Int)
, qui nous dit que ce champ ne peut pas être vide (similaire à NOT NULL
dans MySQL)
C’est tout. Nous avons maintenant une API Go CRUD simple pour travailler avec des marchandises. Nous n'avons pas utilisé la base de données pour cet exemple, mais nous avons examiné comment créer un modèle de données et les manipuler à l'aide de mutations.
Des exemples
Si vous avez téléchargé la source via
go get github.com/graphql-go/graphql
allez dans le répertoire avec un exemple
cd examples/crud
et exécutez l'application
go run main.go
Vous pouvez utiliser les requêtes suivantes:
Obtenir un produit par ID
http://localhost:8080/product?query={product(id:1){name,info,price}}
Obtenir une liste de produits
http://localhost:8080/product?query={list{id,name,info,price}}
Ajouter un nouveau produit
http://localhost:8080/product?query=mutation+_{create(name:"Tequila",info:"Strong alcoholic beverage",price:999){id,name,info,price}}
Edition de produits
http://localhost:8080/product?query=mutation+_{update(id:1,price:195){id,name,info,price}}
Suppression d'un produit par identifiant
http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}
Si vous utilisez REST, faites attention à GraphQL comme alternative possible. Oui, à première vue, cela semble plus difficile, mais cela vaut la peine de commencer et dans quelques jours, vous maîtriserez cette technologie. Au moins, ce sera utile.