Badu-bus:Go 輕量級泛型發佈 - 訂閱事件總線
badu/bus (github.com/badu/bus) 是一個 Go 語言基於泛型實現的輕量級發佈 - 訂閱(Pub/Sub)事件總線庫。它允許不同的組件通過事件機制進行解耦通信,而不需要直接調用彼此的函數。
它解決了什麼問題?
-
組件解耦:發佈者和訂閱者彼此無感知,更靈活、可擴展,便於測試。
-
異步消息:消息可以異步發送和接收,提高系統性能和響應速度。
-
模塊化:有利於將系統拆分爲更小、可維護的模塊。
安裝
go get github.com/badu/bus
示例
我們構建一個解耦的訂單系統,它的業務邏輯包括:
-
訂單創建(order 模塊)
-
通知用戶(notification 模塊)
-
記錄日誌(logging 模塊)
-
自動發貨(shipping 模塊)
當用戶下單時:訂單系統只負責發佈事件,不會直接調用通知、日誌、發貨等模塊。其他模塊獨立監聽事件,執行自己的邏輯。
項目結構
📦 order-system
├── 📂 events # 事件模塊
│ ├── events.go # 事件
├── 📂 order # 訂單模塊
│ ├── order.go # 訂單創建
├── 📂 notification # 通知模塊
│ ├── notify.go # 發送通知
├── 📂 logging # 日誌模塊
│ ├── log.go # 記錄日誌
├── 📂 shipping # 物流模塊
│ ├── ship.go # 自動發貨
├── main.go # 啓動程序
事件(events/events.go)
首先,始終將事件放在單獨的 events 包中,避免循環依賴。所有模塊都會使用它:
package events
// OrderEvent 訂單事件
type OrderEvent struct {
ID string
}
訂單模塊(order/order.go)
訂單模塊負責創建訂單併發布事件,但不關心其他模塊如何處理訂單。
package order
import (
"fmt"
"github.com/badu/bus"
"order-system/events"
)
// PlaceOrder 下單函數
func PlaceOrder(orderID string) {
fmt.Println("🛒 訂單已創建:", orderID)
// 訂單創建後,發佈 "OrderEvent" 事件
bus.Pub(events.OrderEvent{ID: orderID})
}
通知模塊(notification/notify.go)
監聽訂單事件,發送通知。
package notification
import (
"fmt"
"github.com/badu/bus"
"order-system/events"
)
// NotifyUser 發送通知
func NotifyUser(event events.OrderEvent) {
fmt.Println("📢 通知用戶: 訂單", event.ID, "已創建")
}
// Init 初始化時訂閱事件
func Init() {
bus.Sub(NotifyUser)
}
日誌模塊(logging/log.go)
監聽訂單事件,記錄日誌。
package logging
import (
"fmt"
"github.com/badu/bus"
"order-system/events"
)
// LogOrder 記錄訂單日誌
func LogOrder(event events.OrderEvent) {
fmt.Println("📝 記錄日誌: 訂單", event.ID, "已創建")
}
// Init 初始化時訂閱事件
func Init() {
bus.Sub(LogOrder)
}
物流模塊(shipping/ship.go)
監聽訂單事件,自動發貨。
package shipping
import (
"fmt"
"github.com/badu/bus"
"order-system/events"
)
// AutoShip 處理自動發貨
func AutoShip(event events.OrderEvent) {
fmt.Println("🚚 訂單", event.ID, "已進入發貨流程")
}
// Init 初始化時訂閱事件
func Init() {
bus.Sub(AutoShip)
}
主函數(main.go)
在 main.go 中,我們初始化所有訂閱者,觸發訂單創建。
package main
import (
"order-system/logging"
"order-system/notification"
"order-system/order"
"order-system/shipping"
)
func main() {
// 初始化事件訂閱
notification.Init()
logging.Init()
shipping.Init()
// 用戶下單
order.PlaceOrder("12345")
}
運行結果
🛒 訂單已創建: 12345
📢 通知用戶: 訂單 12345 已創建
📝 記錄日誌: 訂單 12345 已創建
🚚 訂單 12345 已進入發貨流程
order 模塊只負責訂單邏輯,而 notification、logging、shipping 模塊各自監聽事件,獨立執行邏輯。
常見問題
示例
// InterestingEvent 定義事件
type InterestingEvent struct {
}
// OnMyEventOccurred 處理函數
func OnMyEventOccurred(event InterestingEvent) {
// do something with the event here
}
bus.Sub(OnMyEventOccurred) // 訂閱
bus.Pub(InterestingEvent{}) // 發佈
如何取消訂閱:
subscription := bus.Sub(OnMyEventOccurred)
// 需要時調用 cancel,OnMyEventOccurred 函數將不再被調用
subscription.Cancel()
只訂閱一次:
// OnMyEventOccurred 處理函數
func OnMyEventOccurred(event InterestingEvent) bool {
// do something with the event here
return true // 事件處理器需返回 true
}
bus.SubCancel(OnMyEventOccurred) // 訂閱
異步處理事件:
bus.PubAsync(InterestingEvent{}) // 發佈
查看已註冊的事件:
bus.Range(func(k, v any) bool {
fmt.Printf("%#v %#v\n", k, v)
return true
})
References
https://github.com/badu/bus
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/Tlbypee6e6uXrwIlyLF0HA