1. 程式人生 > 其它 >9.13Go之函式之事件的響應和處理

9.13Go之函式之事件的響應和處理

9.13Go之函式之事件的響應和處理

什麼是事件系統是實現事件的響應和處理

概念:

  • Go語言將型別的方法與普通函式視為一個概念--->呼叫者無須關心誰來支援呼叫,系統會自動處理是否呼叫普通函式或型別的方法

事件系統的基本原理

概念:

  • 將事件派發者與事件處理者解耦

  • 事件系統的基本原理

一個事件系統擁有的特性:

  • 能夠實現事件的一方,可以根據事件 ID 或名字註冊對應的事件。

  • 事件發起者,會根據註冊資訊通知這些註冊者。

  • 一個事件可以有多個實現方響應。

事件註冊

功能描述:

  • 為外部提供一個註冊入口

  • 註冊入口傳入註冊的事件名稱和對應事件名稱的響應函式

  • 將事件名稱和響應函式關聯並儲存起來

程式碼示例:

package main

/*
例項化一個通過字串對映函式切片的map--->輸入字串找到對映的函式
*/
var event = make(map[string][]func(interface{}))
/*
通過事件名(string)關聯回撥列表([]func(interface{})
同一個事件名稱可能存在多個事件回撥,因此使用回撥列表儲存。回撥的函式宣告為 func(interface{})。
*/

/*
註冊事件:--->形參為
1、事件名
2、回撥函式
提供給外部的通過事件名註冊響應函式的入口。
*/
func RegisterEvent(name string, callBack func(interface{})) {
//事件的列表
list := event[name]
/*
通過事件名(name)進行查詢,返回回撥列表([]func(interface{})
*/

//在列表切片中新增函式
list = append(list, callBack)
/*
為同一個事件名稱在已經註冊的事件回撥的列表中再新增一個回撥函式
*/

//將修改的事件列表切片儲存回去
event[name] = list
/*
將修改後的函式列表設定到 map 的對應事件名中
*/
}

事件呼叫

注意區分事件呼叫方和註冊方:

  • 事件呼叫方是事發現場,負責將事件和事件發生的引數通過事件系統派發出去,而不關心事件到底由誰處理

  • 事件註冊方通過事件系統註冊應該響應哪些事件及如何使用回撥函式處理這些事件。

程式碼示例:

package main

//呼叫事件
func CallEvent(name string, param interface{}) {
//找到事件map對映
list := event[name]
/*
通過註冊事件回撥的 event 和事件名字查詢處理函式列表 list
*/

//遍歷列表找到函式
for _, callback := range list {
/*
遍歷這個事件列表,如果沒有找到對應的事件,list 將是一個空切片
*/

//傳入引數呼叫回撥
callback(param)
}
}

使用事件系統

需求:

  • 在 main() 函式中呼叫事件系統的 CallEvent 生成 OnSkill 事件

  • 這個事件有兩個處理函式,一個是角色的 OnEvent() 方法,還有一個是函式 GlobalEvent()

示例程式碼:

package main

import (
"fmt"
)

/*
新增一個結構體
*/
type Actor struct {

}

/*
為這個結構體新增一個事件處理函式
相當於類的內部方法
*/
func (print *Actor) onEvent(param interface{}) {
//列印內容
fmt.Println("actor event is:", param)
}

/*
定義一個全域性事件
為全域性事件響應函式。有時需要全域性進行偵聽或者處理一些事件,這裡使用普通函式實現全域性事件的處理。
*/
func GlobalEvent(param interface{}) {
fmt.Println("global event is:", param)
}

func main() {
//例項化結構體
ac := new(Actor)

//註冊一個回撥函式
RegisterEvent("OnSkill", ac.onEvent)
/*
註冊一個 OnSkill 事件,實現程式碼由 ac 的 OnEvent 進行處理。也就是 Actor的OnEvent() 方法。
*/

//在註冊的回撥函式上在註冊一個全域性事件
RegisterEvent("Onskill", GlobalEvent)
/*
模擬同一個名稱對應不同的回撥函式的場景
註冊一個 OnSkill 事件,實現程式碼由 GlobalEvent 進行處理
註冊的是同一個名字的事件,但前面註冊的事件不會被覆蓋,而是被新增到事件系統中,關聯 OnSkill 事件的函式列表中。
*/

//呼叫事件
CallEvent("OnSkill", 100)
/*
模擬處理事件,通過 CallEvent() 函式傳入兩個引數,第一個為事件名,第二個為處理函式的引數
*/
}

注意:

  • 事件系統不保證同一個事件實現方多個函式列表中的呼叫順序,事件系統認為所有實現函式都是平等的。

  • 無論例子中的 ac.OnEvent 先註冊,還是 GlobalEvent() 函式先註冊,最終誰先被呼叫,都是無所謂的

  • 一個完善的事件系統還會提供移除單個和所有事件的方法

It's a lonely road!!!