Introduction : Pourquoi GraphQL et Go forment un duo idéal
\nDans le développement web moderne, GraphQL est devenu une norme pour créer des API flexibles et efficaces. Associé au langage Go (Golang), réputé pour ses performances et sa simplicité, vous obtenez un outil puissant pour le développement backend. Dans ce tutoriel étape par étape, nous allons créer une API GraphQL complète en Go à partir de zéro, en utilisant la bibliothèque populaire gqlgen.
Vous apprendrez à configurer le projet, définir le schéma, implémenter les résolveurs et ajouter du middleware pour l'authentification. À la fin de l'article, vous disposerez d'une API fonctionnelle, prête à être intégrée avec n'importe quel frontend.
\n\n1. Configuration du projet et installation des dépendances
\nTout d'abord, créons un nouveau module Go et installons les paquets nécessaires. Assurez-vous d'avoir installé Go version 1.18 ou supérieure.
\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\nMaintenant, initialisons gqlgen dans le projet. Cette commande créera une structure de fichiers de base :
go run github.com/99designs/gqlgen init\nAprès exécution, vous verrez la structure suivante :
\n- \n
graph/— répertoire contenant les fichiers de schéma et de résolveurs \ngraph/schema.graphqls— définition du schéma GraphQL \ngraph/resolver.go— ébauches pour les résolveurs \nserver.go— point d'entrée de l'application \ngqlgen.yml— configuration du générateur \n
2. Définition du schéma GraphQL
\nOuvrons le fichier graph/schema.graphqls et définissons notre modèle de données. Pour l'exemple, créons un système simple de gestion des tâches (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\nAprès avoir enregistré le schéma, lançons la génération de code :
\ngo run github.com/99designs/gqlgen generate\nCette commande créera le fichier graph/model/models_gen.go avec les structures Go et mettra à jour les résolveurs.
3. Implémentation des résolveurs et de la logique métier
\nImplémentons maintenant la logique dans le fichier graph/schema.resolvers.go. Commençons par créer un simple stockage en mémoire (in-memory store) :
// Dans graph/resolver.go, ajoutons le stockage\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}\nImplémentons maintenant les résolveurs pour Query et 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