范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

golang2021面向对象(23)Go语言使用事件系统实现事件的响应和处

  Go语言可以将类型的方法与普通函数视为一个概念,从而简化方法和函数混合作为回调类型时的复杂性。这个特性和  C# 中的代理(delegate)类似,调用者无须关心谁来支持调用,系统会自动处理是否调用普通函数或类型的方法。
   
  本节中,首先将用简单的例子了解Go语言是如何将方法与函数视为一个概念,接着会实现一个事件系统,事件系统能有效地将事件触发与响应两端代码解耦。
  方法和函数的统一调用
  本节的例子将让一个结构体的方法(class.Do)的参数和一个普通函数(funcDo)的参数完全一致,也就是方法与函数的签名一致。然后使用与它们签名一致的函数变量(delegate)分别赋值方法与函数,接着调用它们,观察实际效果。
   
  详细实现请参考下面的代码。
  package  main
  import  "fmt"
  //  声明一个结构体
    type class struct {
    }
  //  给结构体添加Do方法
    func (c *class) Do(v int) {
  fmt.Println("call  method do:", v)
    }
  //  普通函数的Do
    func funcDo(v int) {
  fmt.Println("call  function do:", v)
    }
  func  main() {
  //  声明一个函数回调
        var delegate func(int)
  //  创建结构体实例
        c := new(class)
  //  将回调设为c的Do方法
        delegate = c.Do
  //  调用
        delegate(100)
  //  将回调设为普通函数
        delegate = funcDo
  //  调用
        delegate(100)
    }
  代码说明如下:
  第 10       行,为结构体添加一个 Do() 方法,参数为整型。这个方法的功能是打印提示和输入的参数值。
  第 16       行,声明一个普通函数,参数也是整型,功能是打印提示和输入的参数值。
  第 24       行,声明一个 delegate 的变量,类型为 func(int),与 funcDo 和 class 的 Do() 方法的参数一致。
  第 30 行,将       c.Do 作为值赋给 delegate 变量。
  第 33 行,调用       delegate() 函数,传入 100 的参数。此时会调用 c 实例的 Do() 方法。
  第 36 行,将       funcDo 赋值给 delegate。
  第 39 行,调用       delegate(),传入 100 的参数。此时会调用 funcDo() 方法。
  运行代码,输出如下:
  call method do: 100
  call function do: 100
  这段代码能运行的基础在于:无论是普通函数还是结构体的方法,只要它们的签名一致,与它们签名一致的函数变量就可以保存普通函数或是结构体方法。
   
  了解了Go语言的这一特性后,我们就可以将这个特性用在事件中。
  事件系统基本原理
  事件系统可以将事件派发者与事件处理者解耦。例如,网络底层可以生成各种事件,在网络连接上后,网络底层只需将事件派发出去,而不需要关心到底哪些代码来响应连接上的逻辑。或者再比如,你注册、关注或者订阅某"大V"的社交消息后,"大V"发生的任何事件都会通知你,但他并不用了解粉丝们是如何为她喝彩或者疯狂的。如下图所示为事件系统基本原理图。
   
  图:事件系统基本原理
  一个事件系统拥有如下特性:
  能够实现事件的一方,可以根据事件       ID 或名字注册对应的事件。
  事件发起者,会根据注册信息通知这些注册者。
  一个事件可以有多个实现方响应。
  通过下面的步骤详细了解事件系统的构成及使用。
  事件注册
  事件系统需要为外部提供一个注册入口。这个注册入口传入注册的事件名称和对应事件名称的响应函数,事件注册的过程就是将事件名称和响应函数关联并保存起来,详细实现请参考下面代码的  RegisterEvent() 函数。
  package  main
  //  实例化一个通过字符串映射函数切片的map
    var eventByName = make(map[string][]func(interface{}))
  //  注册事件,提供事件名和回调函数
    func RegisterEvent(name string, callback func(interface{})) {
  //  通过名字查找事件列表
        list := eventByName[name]
  //  在列表切片中添加函数
        list = append(list, callback)
  //  将修改的事件列表切片保存回去
        eventByName[name] = list
    }
  //  调用事件
    func CallEvent(name string, param interface{}) {
  //  通过名字找到事件列表
        list := eventByName[name]
  //  遍历这个事件的所有回调
        for _, callback := range list {
  //  传入参数调用回调
            callback(param)
        }
  }
  代码说明如下:
  第 4 行,创建一个       map 实例,这个 map       通过事件名(string)关联回调列表([]func(interface{}),同一个事件名称可能存在多个事件回调,因此使用回调列表保存。回调的函数声明为       func(interface{})。
  第 7       行,提供给外部的通过事件名注册响应函数的入口。
  第 10       行,eventByName 通过事件名(name)进行查询,返回回调列表([]func(interface{})。
  第 13       行,为同一个事件名称在已经注册的事件回调的列表中再添加一个回调函数。
  第 16       行,将修改后的函数列表设置到 map 的对应事件名中。
  拥有事件名和事件回调函数列表的关联关系后,就需要开始准备事件调用的入口了。
  事件调用
  事件调用方和注册方是事件处理中完全不同的两个角色。事件调用方是事发现场,负责将事件和事件发生的参数通过事件系统派发出去,而不关心事件到底由谁处理;事件注册方通过事件系统注册应该响应哪些事件及如何使用回调函数处理这些事件。事件调用的详细实现请参考上面代码的  CallEvent() 函数。
   
  代码说明如下:
  第 20       行,调用事件的入口,提供事件名称 name 和参数 param。事件的参数表示描述事件具体的细节,例如门打开的事件触发时,参数可以传入谁进来了。
  第 23       行,通过注册事件回调的 eventByName 和事件名字查询处理函数列表 list。
  第 26       行,遍历这个事件列表,如果没有找到对应的事件,list 将是一个空切片。
  第 29       行,将每个函数回调传入事件参数并调用,就会触发事件实现方的逻辑处理。
  使用事件系统
  例子中,在 main()  函数中调用事件系统的 CallEvent 生成 OnSkill 事件,这个事件有两个处理函数,一个是角色的 OnEvent() 方法,还有一个是函数  GlobalEvent(),详细代码实现过程请参考下面的代码。
  package  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)
  //  注册名为OnSkill的回调
        RegisterEvent("OnSkill",  a.OnEvent)
  //  再次在OnSkill上注册全局事件
        RegisterEvent("OnSkill",  GlobalEvent)
  //  调用事件,所有注册的同名函数都会被调用
        CallEvent("OnSkill", 100)
  }
  代码说明如下:
  第 6       行,声明一个角色的结构体。在游戏中,角色是常见的对象,本例中,角色也是 OnSkill 事件的响应处理方。
  第 10       行,为角色结构添加一个 OnEvent() 方法,这个方法拥有 param 参数,类型为       interface{},与事件系统的函数(func(interface{}))签名一致。
  第 16       行为全局事件响应函数。有时需要全局进行侦听或者处理一些事件,这里使用普通函数实现全局事件的处理。
  第 27       行,注册一个 OnSkill 事件,实现代码由 a 的 OnEvent 进行处理。也就是 Actor的OnEvent() 方法。
  第 30       行,注册一个 OnSkill 事件,实现代码由 GlobalEvent       进行处理,虽然注册的是同一个名字的事件,但前面注册的事件不会被覆盖,而是被添加到事件系统中,关联 OnSkill 事件的函数列表中。
  第 33       行,模拟处理事件,通过 CallEvent() 函数传入两个参数,第一个为事件名,第二个为处理函数的参数。
  整个例子运行结果如下:
  actor event: 100
  global event: 100
  结果演示,角色和全局的事件会按注册顺序顺序地触发。
   
  一般来说,事件系统不保证同一个事件实现方多个函数列表中的调用顺序,事件系统认为所有实现函数都是平等的。也就是说,无论例子中的  a.OnEvent 先注册,还是 GlobalEvent() 函数先注册,最终谁先被调用,都是无所谓的,开发者不应该去关注和要求保证调用的顺序。
   
  一个完善的事件系统还会提供移除单个和所有事件的方法。

华为Mate50Pro曝光硬件配置很豪华,不愧是华为华为Mate50Pro延迟发布并不意味着这款手机将缺席。延迟发布的原因,除了缺少零件,芯片技术的限制可能会有突破。您应该知道,华为Mate系列作为重磅的国产手机之一。它不仅有一个独旷视发布智能四向车系统,硬件稳定可靠软件智能调度方案创新4月7日,旷视举办以离散重构,柔性跃升为主题的智能托盘四向车系统新品发布会,重磅推出旷视自研智能托盘四向车PS1500系列常温版和冷库版,介绍旷视河图软件平台在大型托盘四向车项目中36氪首发A轮融资近日,36氪获悉,安杰莱科技(杭州)有限公司(以下简称安杰莱科技)宣布已完成数千万元PreA轮融资。本轮融资将用于产品拓展研发临床试验和商业化推广。安杰莱科技成立于2017年12月被视为元宇宙入口消费电子的下一波机遇会是AR眼镜吗?科创板日报(上海,记者黄心怡),曾一度跌入谷底的ARVR产业,如今因为元宇宙的风口再次大受追捧。面对这一消费电子领域的潜在机遇,国内头部智能手机厂商纷纷摩拳擦掌。其中,AR眼镜作为实测多款App适老版不少设计不合规,入口难找,字小广告多记者实测多款App适老版,发现不少设计不合规,入口难找专区少,内容字小广告多。为助力老年人跨越数字鸿沟,今年1月起,国家工信部开展为期一年的互联网应用适老化及无障碍改造专项行动。首卢伟冰未卜先知?小米12外观出炉,神似RedmiK30S近日网上曝光了小米12的渲染图,从曝光的图片来看,这款机器的背面设计似乎和去年发布的RedmiK30S一样都是矩形相机模组,主摄镜头在上方占很大一部分空间如果是这样的话,那么小宅不这种无底线奇葩吃播,终于被封杀自从几年前4G普及和宽带提速后,互联网视频行业便开始了原地起飞之路。以爱优腾为首的长视频平台收获无数用户,把用户看片习惯狠狠拿捏,额虽然还在亏钱。短视频也完美契合碎片化时代,依靠精小米MIXFold2折叠屏手机渲染图曝光,这外观你喜欢吗?在OPPO抢先一步把折叠屏手机价格打下来的情况下,目前小米MIXFlod2渲染图也随之曝光,从渲染图来看,小米MIXFlod2采用了全新的外观设计,机身更加方正硬朗。图片摘自网络据全面出色才是vivoS12影像性能外观各有千秋说到vivo,大家都会想到其各个系列优秀的影像能力,其中的vivoS系列,更是备受欢迎,每一代会都在影像方面不断提升,前置人像更是一直引领行业。其中vivoS10带来了自然人像美的储能云网融合国网信通1公司子公司安徽继远软件有限公司与国轩高科签订战略合作以来,积极参与储能电站总承包项目建设,同时在用户侧储能电站多样化运营和无人化值守云端j监控方面开展技术研讨和自主产品研发,目前新能源车主必看!关于你的车险,又有新消息今天,中国保险行业协会正式发布新能源汽车商业保险专属条款(试行),备受关注的新能源车三电(电池及储能系统电机及驱动系统其他控制系统)纳入保障范围,涵盖新能源汽车行驶停放充电及作业的
凉了!iOS16支持型号曝光,这些iPhone要被淘汰了时间来到了2022年,安卓鸿蒙手机在系统流畅度性能配置上已经有了突飞猛进的提升,事实上,一部差不多的安卓手机用个两三年还是问题不大的,只不过相较于苹果来说,还是有点差距的,毕竟直到今日热点阿里调整大淘宝组织架构七成清华毕业生体制内就业1微信视频号即将上线付费直播间从微信公开课获悉,微信直播即将上线知识专栏,覆盖多个知识方向。同时,微信视频号即将上线付费直播间。此外,微信直播宣布今年将投入50亿冷启流量包,搭建新生物经济时代加速到来进入新世纪以来,生命科学领域持续取得重大技术突破,生物技术逐渐与信息技术并行成为支撑经济社会发展的底层共性技术,生物技术产品和服务加速以更加亲民的价格更加贴近市场的形态走进千家万户要闻山东省政府与华为公司签署合作备忘录山东省政府与华为公司签署合作备忘录周乃翔出席1月6日下午,山东省人民政府与华为技术有限公司在济南签署共同推进十四五数字强省合作备忘录。省委副书记省长周乃翔,华为公司副董事长轮值董事华为转移多项专利至荣耀公司IT之家1月6日消息,信息显示,近期,荣耀终端有限公司多项专利获授权,包括供电电路一种存储卡识别方法和电子设备等。相关专利法律状态显示,多项专利发生过申请权专利权的转移,变更前权利小米12Pro好评率已降至96,优点很真实,差评却让人哭笑不得小米今年的新款数字旗舰小米12系列已经全面上市,三款新机赶在2021年最后一天首销,且首销5分钟并突破18亿销售额,成绩比去年小米11首销时5分钟15亿销售额还要好。这两天这些大力ONUPDATECURRENTTIMESTAMP请慎用大家好,我是架构摆渡人。这是实践经验系列的第七篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友。今天给大家分享一个容易忽略的问题,正是因为容什么是智能外呼系统?外呼系统就是自动拨打筛选出的客户,并对其播放录音的一个系统,起到了非人工推广宣传的作用。呼出服务,可以用于市场分析,例如可以通过它按照名单自动拨通大量用户,进行业务需求或服务满意度怎么选择一个可靠的支付平台资金是信息的保障对于客户来说,在选择聚合支付服务时,资金信息安全是第一要考虑的因素,一个靠谱的聚合支付服务商,必须拥有安全技术优势,完全符合金融平台安全标准,超强的系统防御能力是用官方开始亮剑张庭多个电商平台已经下架处理,事态再度升级张庭与林瑞阳公司的事情已经走进了一个新的发展进程之中。可以分为两个方面来看。首先就是河北市监督局已经明确了对其上海总公司的定性,并且用传销两个字来说明其公司的经营性质。就目前的市场新能源车准车主的困惑自2021年12月19日起,蔚来et5发布,我第一时间花费2000元订金在APP上订了这款32。5万的车,考虑到到明年9月还不一定有现车,又在懂车帝上反复核实几款新能源车,主要对比