性夜影院午夜看片,无码精品久久一区二区三区,婷婷成人丁香五月综合激情,校园春色 qvod,性调教室高h学校

Golang事件系統(tǒng)Event Bus

本文介紹了事件總線實現(xiàn)。

最近在學(xué)習(xí)開源項目Grafana的代碼,發(fā)現(xiàn)作者實現(xiàn)了一個事件總線的機(jī)制,在項目里面大量應(yīng)用,效果也非常好,代碼也比較簡單,介紹給大家看看。

源碼文件地址:grafana/bus.go at main · grafana/grafana · GitHub

1.注冊和調(diào)用

在這個項目里面隨處可見這種寫法:

Golang事件系統(tǒng)Event Bus

關(guān)鍵是bus.Dispatch(&query)這段代碼,它的參數(shù)是一個結(jié)構(gòu)體GetAlertByIdQuery,內(nèi)容如下:

Golang事件系統(tǒng)Event Bus

根據(jù)名字可以看出這個方法就是通過Id去查詢Alert,其中Alert結(jié)構(gòu)體就是結(jié)果對象,這里就不貼出來了。

通過查看源碼可以得知,Dispatch背后是調(diào)用了GetAlertById這個方法,然后把結(jié)果賦值到query參數(shù)的Result中返回。

Golang事件系統(tǒng)Event Bus

問題來了,這是怎么實現(xiàn)的呢?Dispatch到底做了哪些操作?這樣做有什么好處?

下面我來一一解答:

首先,在Dispatch之前,你需要先注冊這個方法,也就是調(diào)用AddHandler,在這個項目里面可以看到init函數(shù)里面有大量這樣的代碼:

Golang事件系統(tǒng)Event Bus

其實這個方法的邏輯也很簡單,所謂注冊也就是把通過一個map把函數(shù)名和對應(yīng)的函數(shù)做一個映射關(guān)系保存起來,當(dāng)我們Dispatch的時候其實就是通過參數(shù)名查找之前注冊過的函數(shù),然后通過反射調(diào)用該函數(shù)。

Bus結(jié)構(gòu)體里面有幾個map成員,在這個項目里面作者定義了3種不同類型的handler,一種是普通的handler,也就是剛才展示的那種,第二種是帶上下文的handler,還有一種則是事件訂閱用到的handler,我們給一個事件注冊多個監(jiān)聽者,當(dāng)事件觸發(fā)的時候會依次調(diào)用多個監(jiān)聽函數(shù),其實就是一個觀察者模式。

Golang事件系統(tǒng)Event Bus

下面就看看具體的源碼,AddHandler方法內(nèi)容如下:

Golang事件系統(tǒng)Event Bus

Dispatch方法的源碼如下:

Golang事件系統(tǒng)Event Bus

對于AddHandlerCtxDispatchCtx這個2個方法基本上是一樣的,只不過多了一個上下文參數(shù),可以拿來做超時控制或者其它用途。

2.訂閱和發(fā)布

除此之外,還有2個方法AddEventListenerPublish,即事件的訂閱和發(fā)布。

Golang事件系統(tǒng)Event Bus

查看源碼可以得知,可以給一個事件注冊多個handler函數(shù),而Publish的時候則是依次調(diào)用注冊的函數(shù),邏輯也不復(fù)雜。

Golang事件系統(tǒng)Event Bus

這里面有一點不好,所有訂閱函數(shù)的調(diào)用是順序的,并沒有使用協(xié)程,所以如果注冊了很多個函數(shù),這樣效率也不高啊。

3.好處

可能有人會好奇,為什么明明可以直接調(diào)用函數(shù)就行,為啥非得繞個彎子,整這么復(fù)雜?

況且,每次調(diào)用都得使用反射機(jī)制,性能也不行。

我覺得主要有以下幾點:

1.這種寫法邏輯清晰,解耦

2.方便單元測試

3.性能不是最大考量,雖然說反射會降低性能

轉(zhuǎn)自:wangbjun.site/2021/coding/golang/event-bus.html

 

相關(guān)新聞

歷經(jīng)多年發(fā)展,已成為國內(nèi)好評如潮的Linux云計算運(yùn)維、SRE、Devops、網(wǎng)絡(luò)安全、云原生、Go、Python開發(fā)專業(yè)人才培訓(xùn)機(jī)構(gòu)!