Long Polling vs WebSocket en Go : La bataille du temps réel

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Le dilemme du développeur

\n\n

Imaginez : vous développez un chat, un terminal boursier ou un jeu en ligne en Go. Le client doit recevoir les mises à jour instantanément. Le bon vieil AJAX avec interrogation périodique (polling) est exclu — trop de requêtes inutiles qui tuent à la fois le serveur et la batterie de l'utilisateur. Il reste deux candidats : Long Polling (interrogation longue) et WebSocket.

\n\n

Tous deux résolvent le problème du « temps réel », mais le font de manières fondamentalement différentes. Lequel choisir pour votre application Go ? Analysons cela sans blabla, avec des exemples de code concrets et une analyse honnête des avantages et inconvénients. Cet article est votre guide dans le monde des communications en temps réel en Go.

\n\n

Qu'est-ce que le Long Polling en Go ?

\n\n

Le Long Polling est une évolution du polling classique. Le client envoie une requête HTTP au serveur, mais le serveur ne répond pas immédiatement s'il n'y a pas de données. Il « suspend » (maintient la connexion ouverte) et attend qu'un nouvel événement se produise. Dès que l'événement se produit, le serveur envoie une réponse et le client crée immédiatement une nouvelle requête Long Polling. Le cycle se répète.

\n\n

En Go, cela se met en œuvre très élégamment grâce aux goroutines et aux canaux. Le serveur peut « endormir » le gestionnaire de requête jusqu'à l'arrivée des données.

\n\n

Exemple de serveur Long Polling en Go

\n\n
package main\n\nimport (\n    "fmt"\n    "net/http"\n    "time"\n)\n\n// Canal dans lequel arrivent les nouveaux messages\nvar messages = make(chan string, 10)\n\nfunc longPollHandler(w http.ResponseWriter, r *http.Request) {\n    select {\n    case msg := <-messages:\n        fmt.Fprintf(w, "Nouveau message : %s", msg)\n    case <-time.After(30 * time.Second):\n        // Délai d'attente — si aucun message pendant 30 secondes\n        http.Error(w, "Timeout", http.StatusGatewayTimeout)\n    }\n}\n\nfunc main() {\n    // Goroutine simulant l'arrivée de nouveaux messages\n    go func() {\n        for {\n            time.Sleep(5 * time.Second)\n            messages <- fmt.Sprintf("Heure : %s", time.Now().String())\n        }\n    }()\n\n    http.HandleFunc("/poll", longPollHandler)\n    http.ListenAndServe(":8080", nil)\n}\n
\n\n

Le client en JavaScript ressemblera à ceci : après avoir reçu la réponse (ou le délai d'attente), il appelle immédiatement /poll à nouveau. Simple, fiable, fonctionne à travers tous les proxys et pare-feux.

\n\n

WebSocket en Go : Duplex intégral

\n\n

WebSocket est un protocole qui, après une poignée de main (HTTP Upgrade), transforme la connexion en un canal bidirectionnel permanent. Le serveur peut envoyer des données au client à tout moment, et le client au serveur. Pas de requêtes répétées, pas de délais d'attente.

\n\n

En Go, la bibliothèque standard n'a pas de support intégré pour WebSocket, mais il existe un standard de référence — le paquet gorilla/websocket. Il est stable, bien documenté et utilisé en production par des milliers de projets.

\n\n

Exemple de serveur WebSocket en Go

\n\n
package main\n\nimport (\n    "log"\n    "net/http"\n    "time"\n\n    "github.com/gorilla/websocket"\n)\n\nvar upgrader = websocket.Upgrader{\n    CheckOrigin: func(r *http.Request) bool {\n        return true // Pour le développement. En production — vérifier !\n    },\n}\n\nfunc wsHandler(w http.ResponseWriter, r *http.Request) {\n    conn, err := upgrader.Upgrade(w, r, nil)\n    if err != nil {\n        log.Print("Échec de la mise à niveau :", err)\n        return\n    }\n    defer conn.Close()\n\n    // Boucle infinie de lecture et d'écriture\n    for {\n        // Lire un message du client\n        _, message, err := conn.ReadMessage()\n        if err != nil {\n            log.Println("Erreur de lecture :", err)\n            break\n        }\n        log.Printf("Reçu : %s", message)\n\n        // Envoyer une réponse (ou une notification push)\n        err = conn.WriteMessage(websocket.TextMessage, []byte("Serveur : "+time.Now().String()))\n        if err != nil {\n            log.Println("Erreur d'écriture :", err)\n            break\n        }\n    }\n}\n\nfunc main() {\n    http.HandleFunc("/ws", wsHandler)\n    log.Pr                

Blogs

Book Recommendations