Go | 方法與事件的統一呼叫
💬 簡介
在 Go 語言中,方法和函式的處理方式具有相似性,使得兩者在使用上可以互換。這種設計簡化了方法與函式在作為回呼函式時的混用,開發者無需過多關心是呼叫的是普通函式還是結構方法。這種特性對於構建如事件系統等場景具有極大便利。
本文將詳細介紹 Go 語言如何統一呼叫方法與函式,並以此為基礎實現一個簡單的事件系統。
圖片來源:Gophers
🔍 方法與函式的統一呼叫
在 Go 語言中,方法和函式的唯一區別在於方法會綁定一個接收者,而函式則不綁定。只要方法和函式的簽名一致,則可以在程式碼中通過相同的函式變量來呼叫它們。
範例:統一呼叫方法與函式
1 | package main |
📝 在這個範例中,我們將
class
的Do
方法和普通函式funcDo
都賦值給同一個delegate
函式變數,並且能夠根據賦值自動呼叫相應的函式或方法。
🛠 事件系統的實現
利用 Go 的這一特性,我們可以實現一個簡單的事件系統。事件系統的主要目的是解耦事件的觸發與事件的處理者,從而讓系統更靈活、可擴展。
📌 事件註冊
事件註冊是將事件名稱與相應的回呼函式綁定在一起,當事件發生時,系統會根據事件名稱呼叫對應的回呼函式。
1 | package main |
📝 在這個範例中,
RegisterEvent
函式將事件名稱與回呼函式綁定在一起,將回呼函式保存到eventByName
地圖中,這樣當事件發生時可以根據事件名稱來查詢並呼叫回呼函式。
📌 事件呼叫
當事件發生時,系統會呼叫與事件名稱對應的所有回呼函式,並將事件參數傳遞給它們。
1 | // 呼叫事件 |
📝
CallEvent
函式會根據事件名稱查詢回呼函式列表,然後逐一呼叫這些回呼函式並將事件參數傳遞給它們。
🧰 使用事件系統
使用事件系統可以將事件發起方與事件處理方解耦。以下範例展示了如何使用事件系統註冊和呼叫事件。
- 範例:註冊與呼叫事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27package main
import "fmt"
// 定義角色結構
type Actor struct {}
// 角色的事件處理函式
func (a *Actor) OnEvent(param interface{}) {
fmt.Println("actor event:", param)
}
// 全局事件處理函式
func GlobalEvent(param interface{}) {
fmt.Println("global event:", param)
}
func main() {
a := new(Actor)
// 註冊事件
RegisterEvent("OnSkill", a.OnEvent)
RegisterEvent("OnSkill", GlobalEvent)
// 呼叫事件
CallEvent("OnSkill", 100) // 輸出: actor event: 100 global event: 100
}📝 在這個範例中,我們註冊了兩個回呼函式來處理
OnSkill
事件,這些回呼函式分別來自角色的OnEvent
方法和全局的GlobalEvent
函式。當事件被呼叫時,這些回呼函式會按照註冊順序被執行。
⚠️ 注意事項
- 事件回呼順序:
- 事件系統並不保證回呼函式的呼叫順序,這意味著不同的回呼函式可能會按照不同的順序執行。如果需要確保回呼順序,可以自行管理回呼的執行順序。
- 重複註冊:
- 對同一事件註冊多個回呼函式時,它們會被按順序執行,不會互相覆蓋。
🎯 總結
- Go 語言允許方法和函式具有相同的簽名,因此可以將它們視為統一的概念來處理。
- 基於這一特性,我們可以輕鬆實現事件系統,將事件的發起與處理解耦,並在需要時動態註冊和呼叫事件回呼。
- 雖然事件系統提供了極大的靈活性,但需要注意回呼函式的順序執行問題,以及如何處理多次註冊相同事件的情況。
最後建議回顧一下 Go | 菜鳥教學 目錄,了解其章節內容。
註:以上參考了
Go