WebSocket en Go : création d'applications temps réel de niveau avancé

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 : au-delà du simple WebSocket en Go



Les exemples de base de WebSocket en Go montrent généralement une simple connexion écho. Dans les projets de production réels — des terminaux boursiers aux jeux multijoueurs et systèmes d'alerte — il faut bien plus : gestion des salles, arrêt progressif, mise à l'échelle et gestion correcte des erreurs. Dans cet article, nous allons analyser un modèle avancé de construction d'applications temps réel en Go utilisant la bibliothèque gorilla/websocket.



Nous allons créer une architecture basée sur Hub (répartiteur central) et Client (connexion individuelle), ajouter la prise en charge des salles, un mécanisme de tolérance aux pannes et montrer comment arrêter correctement le serveur.



Architecture Hub et Client : base du serveur temps réel



Pourquoi un Hub ?

Chaque client WebSocket est une goroutine distincte. Les gérer directement depuis le gestionnaire HTTP est dangereux : cela entraîne des conditions de concurrence et des fuites mémoire. Le modèle Hub résout ce problème en agissant comme un canal unique pour l'enregistrement, la suppression et la diffusion des messages.



Implémentation du Hub

package main

import ( "log" "sync")

type Client struct { hub *Hub send chan []byte room string}

type Hub struct { clients map[*Client]bool broadcast chan Message register chan *Client unregister chan *Client mu sync.RWMutex}

type Message struct { Room string Data []byte Sender *Client}

func NewHub() *Hub { return &Hub{ clients: make(map[*Client]bool), broadcast: make(chan Message, 256), register: make(chan *Client), unregister: make(chan *Client), }}

func (h *Hub) Run() { for { select { case client := <-h.register: h.mu.Lock() h.clients[client] = true h.mu.Unlock() log.Printf("Client connecté. Total : %d", len(h.clients))

case client := <-h.unregister: h.mu.Lock() if _, ok := h.clients[client]; ok { delete(h.clients, client) close(client.send) } h.mu.Unlock()

case message := <-h.broadcast: h.mu.RLock() for client := range h.clients { // Envoyer uniquement dans la bonne salle if client.room == message.Room || message.Room == "" { select { case client.send <- message.Data: default: // Si le canal est saturé — déconnecter le client h.mu.RUnlock() h.unregister <- client h.mu.RLock() } } } h.mu.RUnlock() } }}


Points clés :

  • Canaux — register, unregister, broadcast — synchronisent en toute sécurité les goroutines.
  • RWMutex — permet de lire simultanément la liste des clients, mais bloque l'écriture.
  • Routage par salle — le message est envoyé uniquement aux clients de la même salle.


Gestion des salles et des abonnements



Les salles (Rooms) sont des groupes logiques de clients. Par exemple, dans un chat, chaque conversation a sa propre salle. Dans notre Hub, la salle est définie par le champ room du Client. Voyons comment un client s'abonne à une salle.



Gestionnaire HTTP avec mise à niveau WebSocket

import (    "net/http"    "github.com/gorilla/websocket")

var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { return true // Pour la production, remplacer par une vérification de l'origine },}

func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err !=

Blogs

Book Recommendations