Introduction : pourquoi Go pour une API REST ?
\nGo (Golang) est un langage compilé moderne avec un support intégré de la concurrence et des performances élevées. Une API REST en Go fonctionne rapidement, consomme peu de mémoire et se scale facilement. En 30 minutes, vous créerez un service REST complet avec des requêtes GET, POST, PUT et DELETE, en utilisant uniquement la bibliothèque standard.
\nDans ce guide, nous allons écrire une API pour gérer une liste de tâches (application Todo). Vous apprendrez à configurer le routage, à traiter le JSON, à ajouter un middleware pour la journalisation et à retourner correctement les erreurs. Sans frameworks externes — que du Go pur !
\n\n1. Configuration du projet et structure
\nCréez un nouveau répertoire pour le projet et initialisez le module Go :
\nmkdir go-todo-api\ncd go-todo-api\ngo mod init todo-api\nLa structure du projet sera simple :
\n- \n
main.go— point d'entrée et démarrage du serveur \nhandlers.go— gestionnaires de requêtes \nmodels.go— structures de données \nmiddleware.go— middleware \n
Créez le fichier models.go avec la structure de la tâche :
package main\n\ntype Task struct {\n ID int `json:"id"`\n Title string `json:"title"`\n Completed bool `json:"completed"`\n}\nNous stockerons les tâches en mémoire (slice tasks) pour simplifier. Dans un projet réel, utilisez une base de données.
\n\n2. Routage et gestionnaires
\nGo utilise le package intégré net/http. Créons le fichier handlers.go avec les gestionnaires principaux.
2.1. GET /tasks — récupération de toutes les tâches
\npackage main\n\nimport (\n "encoding/json"\n "net/http"\n "strconv"\n)\n\nvar tasks = []Task{}\nvar nextID = 1\n\nfunc getTasks(w http.ResponseWriter, r *http.Request) {\n w.Header().Set("Content-Type", "application/json")\n json.NewEncoder(w).Encode(tasks)\n}\n2.2. POST /tasks — création d'une nouvelle tâche
\nfunc createTask(w http.ResponseWriter, r *http.Request) {\n var newTask Task\n if err := json.NewDecoder(r.Body).Decode(&newTask); err != nil {\n http.Error(w, "Invalid JSON", http.StatusBadRequest)\n return\n }\n newTask.ID = nextID\n nextID++\n tasks = append(tasks, newTask)\n w.Header().Set("Content-Type", "application/json")\n w.WriteHeader(http.StatusCreated)\n json.NewEncoder(w).Encode(newTask)\n}\n2.3. PUT /tasks/{id} — mise à jour d'une tâche
\nfunc updateTask(w http.ResponseWriter, r *http.Request) {\n idStr := r.PathValue("id")\n id, err := strconv.Atoi(idStr)\n if err != nil {\n http.Error(w, "Invalid task ID", http.StatusBadRequest)\n return\n }\n \n var updatedTask Task\n if err := json.NewDecoder(r.Body).Decode(&updatedTask); err != nil {\n http.Error(w, "Invalid JSON", http.StatusBadRequest)\n return\n }\n \n for i, t := range tasks {\n if t.ID == id {\n tasks[i].Title = updatedTask.Title\n tasks[i].Completed = updatedTask.Completed\n w.Header().Set("Content-Type", "application/json")\n json.NewEncoder(w).Encode(tasks[i])\n return\n }\n }\n http.Error(w, "Task not found", http.StatusNotFound)\n}\n2.4. DELETE /tasks/{id} — suppression d'une tâche
\nfunc deleteTask(w http.ResponseWriter, r *http.Request) {\n idStr := r.PathValue("id")\n id, err := strconv.Atoi(idStr)\n if err != nil {\n http.Error(w, "Invalid task ID", http.StatusBadRequest)\n return\n }\n \n for i, t := range tasks {\n if t.ID == id {\n tasks = append(tasks[:i], tasks[i+1:]...)\n w.WriteHeader(http.StatusNoContent)\n return\n }\n }\n http.Error(w, "Task not found", http.StatusNotFound)\n}\nNotez bien