Ajout de Swagger à votre API Go
Générer automatiquement les documents OpenAPI à partir des annotations de code
La documentation d’API est cruciale pour toute application moderne, et pour les API Go Swagger, (OpenAPI) est devenu le standard de l’industrie. Pour les développeurs Go, swaggo offre une solution élégante pour générer une documentation d’API complète directement à partir des annotations du code.
Cette belle image est générée par le modèle IA Flux 1 dev.
Pourquoi Swagger est essentiel pour les API Go
Lors de la création d’API REST, la documentation devient souvent obsolète au fur et à mesure que le code évolue. Swagger résout ce problème en générant la documentation à partir de votre code source, garantissant ainsi qu’elle reste synchronisée avec votre implémentation. L’interface utilisateur interactive de Swagger permet aux développeurs de tester les points d’accès directement depuis le navigateur, améliorant considérablement l’expérience de développement.
Pour les équipes construisant des microservices ou des API publiques, la documentation Swagger devient essentielle pour :
- Génération de clients : Créer automatiquement des bibliothèques de clients dans plusieurs langages
- Tests de contrat : Valider les requêtes et les réponses par rapport aux schémas définis
- Collaboration d’équipe : Fournir une source de vérité unique pour les contrats d’API
- Intégration des nouveaux développeurs : Les nouveaux membres de l’équipe peuvent explorer les API de manière interactive
Démarrage avec swaggo
La bibliothèque swaggo est l’outil le plus populaire pour ajouter le support Swagger aux applications Go. Elle fonctionne en analysant des commentaires spéciaux dans votre code et en générant des fichiers de spécification OpenAPI 3.0.
Installation
Installez d’abord l’outil CLI swag :
go install github.com/swaggo/swag/cmd/swag@latest
Ensuite, ajoutez le package middleware Swagger approprié pour votre framework. Pour Gin :
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
Pour Echo :
go get -u github.com/swaggo/echo-swagger
Pour Fiber :
go get -u github.com/gofiber/swagger
Configuration de base
Commencez par ajouter les informations générales de l’API dans votre fichier main.go. De la même manière que vous structureriez une API REST en Go, les annotations doivent être claires et descriptives :
// @title Product API
// @version 1.0
// @description A product management API with Swagger documentation
// @termsOfService http://swagger.io/terms/
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:8080
// @BasePath /api/v1
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description Type "Bearer" followed by a space and JWT token.
func main() {
// Your application code
}
Implémentation avec le Framework Gin
Implémentons un exemple complet en utilisant Gin. D’abord, définissez vos modèles de données avec des étiquettes de structure :```go
type Product struct {
ID int json:"id" example:"1"
Name string json:"name" example:"Laptop" binding:"required"
Description string json:"description" example:"High-performance laptop"
Price float64 json:"price" example:"999.99" binding:"required,gt=0"
Stock int json:"stock" example:"50"
}
type ErrorResponse struct {
Error string json:"error" example:"Invalid input"
Message string json:"message" example:"Product name is required"
}
Maintenant, annotez vos fonctions de traitement. Lors du travail avec des [opérations de base de données](https://www.glukhov.org/fr/app-architecture/data-access/comparing-go-orms-gorm-ent-bun-sqlc/ "Comparaison des ORM Go pour PostgreSQL : GORM vs Ent vs Bun vs sqlc - avec des exemples de code"), ces annotations aident à documenter le flux de données :
```go
// GetProduct godoc
// @Summary Get product by ID
// @Description Retrieve a single product by its unique identifier
// @Tags products
// @Accept json
// @Produce json
// @Param id path int true "Product ID"
// @Success 200 {object} Product
// @Failure 400 {object} ErrorResponse
// @Failure 404 {object} ErrorResponse
// @Router /products/{id} [get]
func GetProduct(c *gin.Context) {
id := c.Param("id")
// Implementation here
c.JSON(200, Product{ID: 1, Name: "Laptop", Price: 999.99})
}
// CreateProduct godoc
// @Summary Create a new product
// @Description Add a new product to the catalog
// @Tags products
// @Accept json
// @Produce json
// @Param product body Product true "Product object"
// @Success 201 {object} Product
// @Failure 400 {object} ErrorResponse
// @Security Bearer
// @Router /products [post]
func CreateProduct(c *gin.Context) {
var product Product
if err := c.ShouldBindJSON(&product); err != nil {
c.JSON(400, ErrorResponse{Error: "Bad Request", Message: err.Error()})
return
}
// Save to database
c.JSON(201, product)
}
Génération de la documentation
Après avoir annoté votre code, générez la documentation Swagger :
swag init
Cela crée un dossier docs contenant swagger.json, swagger.yaml et des fichiers Go. Importez et enregistrez le point d’accès Swagger :
package main
import (
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
_ "yourproject/docs" // Import generated docs
)
func main() {
r := gin.Default()
// API routes
v1 := r.Group("/api/v1")
{
v1.GET("/products/:id", GetProduct)
v1.POST("/products", CreateProduct)
}
// Swagger endpoint
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
r.Run(":8080")
}
Accédez maintenant à votre documentation d’API interactive sur http://localhost:8080/swagger/index.html.
Implémentation avec le Framework Echo
Les utilisateurs d’Echo suivent un schéma similaire, mais avec des middlewares spécifiques à Echo :
package main
import (
"github.com/labstack/echo/v4"
echoSwagger "github.com/swaggo/echo-swagger"
_ "yourproject/docs"
)
func main() {
e := echo.New()
// API routes
api := e.Group("/api/v1")
api.GET("/products/:id", getProduct)
api.POST("/products", createProduct)
// Swagger endpoint
e.GET("/swagger/*", echoSwagger.WrapHandler)
e.Start(":8080")
}
Implémentation avec le Framework Fiber
L’implémentation de Fiber est tout aussi simple :
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/swagger"
_ "yourproject/docs"
)
func main() {
app := fiber.New()
// API routes
api := app.Group("/api/v1")
api.Get("/products/:id", getProduct)
api.Post("/products", createProduct)
// Swagger endpoint
app.Get("/swagger/*", swagger.HandlerDefault)
app.Listen(":8080")
}
Annotations Swagger avancées
Documenter des corps de requête complexes
Pour les structures imbriquées ou les tableaux :
type CreateOrderRequest struct {
CustomerID int `json:"customer_id" example:"123" binding:"required"`
Items []OrderItem `json:"items" binding:"required,min=1"`
ShippingAddress Address `json:"shipping_address" binding:"required"`
}
type OrderItem struct {
ProductID int `json:"product_id" example:"1" binding:"required"`
Quantity int `json:"quantity" example:"2" binding:"required,min=1"`
}
type Address struct {
Street string `json:"street" example:"123 Main St" binding:"required"`
City string `json:"city" example:"New York" binding:"required"`
ZipCode string `json:"zip_code" example:"10001" binding:"required"`
}
// CreateOrder godoc
// @Summary Create a new order
// @Description Create an order with multiple items and shipping information
// @Tags orders
// @Accept json
// @Produce json
// @Param order body CreateOrderRequest true "Order details"
// @Success 201 {object} Order
// @Failure 400 {object} ErrorResponse
// @Failure 422 {object} ErrorResponse
// @Security Bearer
// @Router /orders [post]
func CreateOrder(c *gin.Context) {
// Implementation
}
Documenter les téléchargements de fichiers
// UploadImage godoc
// @Summary Upload product image
// @Description Upload an image file for a product
// @Tags products
// @Accept multipart/form-data
// @Produce json
// @Param id path int true "Product ID"
// @Param file formData file true "Image file"
// @Success 200 {object} map[string]string
// @Failure 400 {object} ErrorResponse
// @Security Bearer
// @Router /products/{id}/image [post]
func UploadImage(c *gin.Context) {
file, _ := c.FormFile("file")
// Handle upload
}
Paramètres de requête et pagination
// ListProducts godoc
// @Summary List products with pagination
// @Description Get paginated list of products with optional filtering
// @Tags products
// @Accept json
// @Produce json
// @Param page query int false "Page number" default(1)
// @Param page_size query int false "Items per page" default(10)
// @Param category query string false "Filter by category"
// @Param min_price query number false "Minimum price"
// @Param max_price query number false "Maximum price"
// @Success 200 {array} Product
// @Failure 400 {object} ErrorResponse
// @Router /products [get]
func ListProducts(c *gin.Context) {
// Implementation with pagination
}
Authentification et Sécurité
Documentez différentes méthodes d’authentification dans votre API. Pour les applications multi-locataires, une documentation d’authentification appropriée est cruciale :
Authentification par jeton Bearer
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description Type "Bearer" followed by a space and JWT token.
Authentification par clé API
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name X-API-Key
// @description API key for authentication
Authentification OAuth2
// @securitydefinitions.oauth2.application OAuth2Application
// @tokenUrl https://example.com/oauth/token
// @scope.write Grants write access
// @scope.admin Grants read and write access to administrative information
Authentification de base
// @securityDefinitions.basic BasicAuth
Appliquez la sécurité à des points d’accès spécifiques :
// @Security Bearer
// @Security ApiKeyAuth
Personnalisation de l’interface Swagger UI
Vous pouvez personnaliser l’apparence et le comportement de l’interface Swagger UI :
// Custom configuration
url := ginSwagger.URL("http://localhost:8080/swagger/doc.json")
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
// With custom title
r.GET("/swagger/*any", ginSwagger.WrapHandler(
swaggerFiles.Handler,
ginSwagger.URL("http://localhost:8080/swagger/doc.json"),
ginSwagger.DefaultModelsExpandDepth(-1),
))
Pour désactiver Swagger en production :
if os.Getenv("ENV") != "production" {
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}
Intégration avec CI/CD
Automatisez la génération de la documentation Swagger dans votre pipeline CI/CD :
# GitHub Actions example
name: Generate Swagger Docs
on: [push]
jobs:
swagger:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Install swag
run: go install github.com/swaggo/swag/cmd/swag@latest
- name: Generate Swagger docs
run: swag init
- name: Commit docs
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git add docs/
git commit -m "Update Swagger documentation" || exit 0
git push
Bonnes pratiques
1. Style d’annotation cohérent
Maintenez un formatage cohérent sur tous les points d’accès :
// HandlerName godoc
// @Summary Brief description (under 50 chars)
// @Description Detailed description of what the endpoint does
// @Tags resource-name
// @Accept json
// @Produce json
// @Param name location type required "description"
// @Success 200 {object} ResponseType
// @Failure 400 {object} ErrorResponse
// @Router /path [method]
2. Utiliser des exemples descriptifs
Ajoutez des exemples réalistes pour aider les consommateurs de l’API :
type User struct {
ID int `json:"id" example:"1"`
Email string `json:"email" example:"user@example.com"`
CreatedAt time.Time `json:"created_at" example:"2025-01-15T10:30:00Z"`
}
3. Documenter tous les codes de réponse
Incluez tous les codes de statut HTTP possibles :
// @Success 200 {object} Product
// @Success 201 {object} Product
// @Failure 400 {object} ErrorResponse "Bad Request"
// @Failure 401 {object} ErrorResponse "Unauthorized"
// @Failure 403 {object} ErrorResponse "Forbidden"
// @Failure 404 {object} ErrorResponse "Not Found"
// @Failure 422 {object} ErrorResponse "Validation Error"
// @Failure 500 {object} ErrorResponse "Internal Server Error"
4. Versionner votre API
Utilisez un versionnement approprié dans le chemin de base :
// @BasePath /api/v1
Et organisez votre code en conséquence :
v1 := r.Group("/api/v1")
v2 := r.Group("/api/v2")
5. Regrouper les points d’accès liés
Utilisez des étiquettes pour organiser logiquement les points d’accès :
// @Tags products
// @Tags orders
// @Tags users
6. Garder la documentation à jour
Exécutez swag init avant chaque engagement ou intégrez-le dans votre processus de construction :
#!/bin/bash
# pre-commit hook
swag init
git add docs/
Tester la documentation Swagger
Lors du travail avec des architectures serverless comme AWS Lambda, le test de votre documentation d’API devient encore plus important :
func TestSwaggerGeneration(t *testing.T) {
// Verify swagger.json exists
_, err := os.Stat("./docs/swagger.json")
if err != nil {
t.Fatal("swagger.json not found, run 'swag init'")
}
// Verify swagger endpoint responds
r := setupRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/swagger/index.html", nil)
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
}
Problèmes courants et solutions
La documentation ne se met pas à jour
Si les modifications n’apparaissent pas, assurez-vous de régénérer la documentation :
swag init --parseDependency --parseInternal
Le drapeau --parseDependency analyse les dépendances externes, et --parseInternal analyse les packages internes.
Types personnalisés non reconnus
Pour les types issus de packages externes, utilisez l’étiquette swaggertype :
type CustomTime struct {
time.Time
}
func (CustomTime) SwaggerDoc() map[string]string {
return map[string]string{
"time": "RFC3339 timestamp",
}
}
Ou utilisez l’étiquette swaggertype :
type Product struct {
ID int `json:"id"`
UpdatedAt CustomTime `json:"updated_at" swaggertype:"string" format:"date-time"`
}
Tableaux et énumérations
Documentez les types de tableau et les énumérations :
type Filter struct {
Status []string `json:"status" enums:"active,inactive,pending"`
Tags []string `json:"tags"`
}
// @Param status query string false "Status filter" Enums(active, inactive, pending)
Approches alternatives
Bien que swaggo soit le choix le plus populaire, d’autres options existent :
go-swagger
Une alternative plus complète mais plus complexe :
brew install go-swagger
swagger generate spec -o ./swagger.json
Fichiers OpenAPI manuels
Pour un contrôle total, écrivez manuellement des spécifications OpenAPI en YAML :
openapi: 3.0.0
info:
title: Product API
version: 1.0.0
paths:
/products:
get:
summary: List products
responses:
'200':
description: Success
Ensuite, servez-les avec :
r.StaticFile("/openapi.yaml", "./openapi.yaml")
Intégration avec l’IA et les LLMs
Lors de la création d’API qui s’intègrent à des services d’IA, une documentation appropriée devient cruciale. Par exemple, lors du travail avec des sorties structurées de LLMs, Swagger aide à documenter les schémas de requêtes et de réponses complexes :
type LLMRequest struct {
Prompt string `json:"prompt" example:"Summarize this text"`
Model string `json:"model" example:"qwen2.5:latest"`
Temperature float64 `json:"temperature" example:"0.7" minimum:"0" maximum:"2"`
MaxTokens int `json:"max_tokens" example:"1000" minimum:"1"`
Schema map[string]interface{} `json:"schema,omitempty"`
}
// GenerateStructured godoc
// @Summary Generate structured LLM output
// @Description Generate text with constrained output schema
// @Tags llm
// @Accept json
// @Produce json
// @Param request body LLMRequest true "LLM parameters"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} ErrorResponse
// @Router /llm/generate [post]
func GenerateStructured(c *gin.Context) {
// Implementation
}
Considérations de performance
La documentation Swagger a un impact de performance minimal :
- Temps de construction :
swag initprend 1 à 3 secondes pour la plupart des projets - Temps d’exécution : La documentation est chargée une seule fois au démarrage
- Mémoire : Ajoute généralement 1-2 Mo à la taille du binaire
- Temps de réponse : Aucun impact sur les points d’accès de l’API eux-mêmes
Pour les très grandes API (plus de 100 points d’accès), envisagez :
- Le découpage en plusieurs fichiers Swagger
- Le chargement paresseux des assets de l’interface Swagger UI
- La fourniture de la documentation depuis un service séparé
Considérations de sécurité
Lors de l’exposition de la documentation Swagger :
- Désactiver en production (si l’API est interne) :
if os.Getenv("ENV") == "production" {
// Don't register Swagger endpoint
return
}
- Ajouter l’authentification :
authorized := r.Group("/swagger")
authorized.Use(AuthMiddleware())
authorized.GET("/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
- Mettre en place une limite de débit sur le point d’accès :
r.GET("/swagger/*any", RateLimitMiddleware(), ginSwagger.WrapHandler(swaggerFiles.Handler))
- Ne jamais exposer de détails internes :
- Ne documentez pas les points d’accès internes
- Évitez d’exposer directement les schémas de base de données
- Nettoyez les messages d’erreur dans la documentation
Conclusion
L’ajout de la documentation Swagger à votre API Go transforme l’expérience de développement d’une approche basée sur la conjecture à une exploration guidée. La bibliothèque swaggo simplifie ce processus en générant une documentation OpenAPI complète à partir de vos annotations de code.
Points clés à retenir :
- Commencez par des annotations de base et développez-les progressivement
- Gardez la documentation synchronisée avec le code via CI/CD
- Utilisez l’interface Swagger UI pour des tests interactifs pendant le développement
- Documentez en détail l’authentification, les erreurs et les cas limites
- Tenez compte des implications de sécurité lors de l’exposition de la documentation
Que vous construisiez des microservices, des API publiques ou des outils internes, la documentation Swagger rapporte des dividendes sous forme de réduction de la charge de support, d’intégration plus rapide et d’une meilleure conception d’API. L’investissement initial pour apprendre la syntaxe d’annotation devient rapidement une routine, et la génération automatisée garantit que votre documentation ne retarde jamais par rapport à votre implémentation.
Pour les développeurs Go, la combinaison de la typage fort, de la génération de code et du système d’annotation de swaggo crée un flux de travail puissant qui rend la documentation d’API une partie naturelle du processus de développement plutôt qu’un après-coup.
Si la pile HTTP sous-jacente est toujours une question ouverte, Frameworks Web Go en 2026 : net/http, chi, Gin, Echo, Fiber Comparés compare les cinq options sur la même charge de travail, de sorte que la décision du framework peut être réglée avant que les outils de documentation ne soient câblés.
Liens utiles
- Aide-mémoire Go
- Construire des API REST en Go
- Frameworks Web Go en 2026 : net/http, chi, Gin, Echo, Fiber Comparés
- Comparaison des ORM Go pour PostgreSQL : GORM vs Ent vs Bun vs sqlc
- Modèles de base de données multi-locataires avec des exemples en Go
- LLMs avec sorties structurées : Ollama, Qwen3 & Python ou Go
- Performance AWS lambda : JavaScript vs Python vs Golang