Event Bus et le pattern Observer en Go (Golang) : de la théorie à la pratique
\nLe pattern Observer et son implémentation sous forme d'Event Bus sont des outils fondamentaux pour construire des systèmes faiblement couplés et évolutifs. En Go, avec sa philosophie « communiquez via des canaux, pas via la mémoire partagée », ces patterns acquièrent une élégance particulière. Dans cet article, nous allons voir comment créer votre propre Event Bus en Go, en utilisant des goroutines et des canaux, et examiner des scénarios d'utilisation typiques.
\n\nPattern Observer : essence et problème
\nImaginez que vous ayez un système où un objet (l'éditeur) doit notifier plusieurs autres (les abonnés) d'un changement d'état. Sans Observer, vous devriez lier rigidement l'éditeur à chaque abonné. Observer résout cela en introduisant une interface d'abonnement : l'éditeur stocke une liste d'abonnés et appelle leur méthode Update() lorsqu'un événement se produit.
Event Bus est un bus centralisé qui joue le rôle d'intermédiaire. N'importe quel composant peut publier un événement, et n'importe quel autre peut s'y abonner, sans connaître l'existence de l'autre.
\n\nPourquoi Go est-il idéal pour un Event Bus ?
\n- \n
- Goroutines et canaux : traitement asynchrone des événements sans blocage. \n
- Interfaces : permettent de définir facilement des contrats pour les gestionnaires. \n
- Absence d'héritage : la composition via des canaux et des fonctions est plus naturelle qu'une implémentation OOP classique. \n
Implémentation simple d'un Event Bus en Go
\nCommençons par une version de base, où les événements sont des chaînes de caractères et les abonnés sont des fonctions de gestion.
\n\npackage main\n\nimport (\n "fmt"\n "sync"\n "time"\n)\n\n// EventBus — notre bus d'événements\ntype EventBus struct {\n subscribers map[string][]func(string)\n mu sync.RWMutex\n}\n\n// NewEventBus crée un nouveau bus\nfunc NewEventBus() *EventBus {\n return &EventBus{\n subscribers: make(map[string][]func(string)),\n }\n}\n\n// Subscribe abonne un gestionnaire à un événement\nfunc (eb *EventBus) Subscribe(event string, handler func(string)) {\n eb.mu.Lock()\n defer eb.mu.Unlock()\n eb.subscribers[event] = append(eb.subscribers[event], handler)\n}\n\n// Publish publie un événement et appelle tous les abonnés de manière synchrone\nfunc (eb *EventBus) Publish(event string, data string) {\n eb.mu.RLock()\n defer eb.mu.RUnlock()\n if handlers, ok := eb.subscribers[event]; ok {\n for _, handler := range handlers {\n handler(data)\n }\n }\n}\n\nfunc main() {\n bus := NewEventBus()\n \n bus.Subscribe("user.login", func(data string) {\n fmt.Printf("Connexion : %s\\n", data)\n })\n \n bus.Subscribe("user.login", func(data string) {\n fmt.Printf("Audit : %s s'est connecté\\n", data)\n })\n \n bus.Publish("user.login", "alice@example.com")\n // Sortie :\n // Connexion : alice@example.com\n // Audit : alice@example.com s'est connecté\n}\n\nCe code fonctionne, mais il y a un détail : les gestionnaires sont appelés de manière synchrone. Si un gestionnaire se bloque, il bloquera tout le bus.
\n\nVersion asynchrone avec des canaux
\nAjoutons de l'asynchronisme via des canaux tamponnés. Chaque abonné recevra son propre canal.
\n\ntype AsyncEventBus struct {\n subscribers map[string][]chan string\n mu sync.RWMutex\n}\n\nfunc NewAsyncEventBus() *AsyncEventBus {\n return &AsyncEventBus{\n subscribers: make(map[string][]chan string),\n }\n}\n\nfunc (eb *AsyncEventBus) Subscribe(event string, buffer int) <-chan string {\n eb.mu.Lock()\n defer eb.mu.Unlock()\n ch := make(chan string, buffer)\n eb.subscribers[event] = append(eb.subscribers[event], ch)\n return ch\n}\n\nfunc (eb *AsyncEventBus) Publish(event string, data string) {\n eb.mu.RLock()\n defer eb.mu.RUnlock()\n if channe Aussi dans la bibliothèque
Planificateur de tâches PHP : bibliothèque cron‑expression pour un planning flexible
Travail avec les dates en Swift (iOS/macOS) : bibliothèques et outils
Envoi de SMS en Java : aperçu des bibliothèques API (Twilio, Nexmo, passerelles SMS)
Ehcache Java : guide complet avec exemples
Générateur de QR codes en Go (Golang) avec la bibliothèque go-qrcode