Badu-bus:Go 輕量級泛型發佈 - 訂閱事件總線

badu/bus (github.com/badu/bus) 是一個 Go 語言基於泛型實現的輕量級發佈 - 訂閱(Pub/Sub)事件總線庫。它允許不同的組件通過事件機制進行解耦通信,而不需要直接調用彼此的函數。

它解決了什麼問題?

安裝

go get github.com/badu/bus

示例

我們構建一個解耦的訂單系統,它的業務邏輯包括:

當用戶下單時:訂單系統只負責發佈事件,不會直接調用通知、日誌、發貨等模塊。其他模塊獨立監聽事件,執行自己的邏輯。

項目結構

📦 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