当前位置: 首页 > news >正文

go 事件机制(观察者设计模式)

背景:

    公司目前有个业务,收到数据后,要分发给所有的客户端或者是业务模块,类似消息通知这样的需求,自然而然就想到了事件,观察者比较简单就自己实现以下,确保最小功能使用支持即可,其他的后期进行支持就行。

  • 创建事件结构体,用来发送事件信息
// Event
// @Description: 事件信息,作用:发生的动作或事情的描述
type Event struct {//默认false,进行同步处理;true异步处理AsyncHandle bool//事件名称EventName string//目标数据Data any
}
  • 创建事件监听者
// EventListener 定义监听器;事件监听器是一个函数,它接收事件并对其作出响应
type EventListener func(*Event)
  • 创建分发器,这快也可以不用这些,可以写到分发管理器里也是可以的,我这边主要是为了后期方便扩展使用的
// dispatcher
// @Description: 事件分发器
type dispatcher struct {//存储事件监听器,通过名称进行分组listeners map[string][]EventListener
}// NewDispatcher
//
//	@Author  zhaosy
//	@Description: 新建分发器,不允许对外开放
//	@date  2024-08-07 17:12:36
func newDispatcher() *dispatcher {return &dispatcher{listeners: make(map[string][]EventListener),}
}
  • 创建分发管理以及相关业务
// 定义全局分发管理器
var eventDispatcherManagerObj = &eventDispatcherManager{dispatcher:      newDispatcher(),RegisterChannel: make(chan *eventListenerInfo),//容量给1000,后续可以根据情况进行设置大小即可EventChannel: make(chan *Event, 1000),
}func init() {//异步进行启动go eventDispatcherManagerObj.Start()
}// eventListenerInfo
// @Description: 监听者封装,供内部使用
type eventListenerInfo struct {EventName stringEventListener
}// eventDispatcherManager
// @Description: 事件分发处理器,供内部使用
type eventDispatcherManager struct {*dispatcherRegisterChannel chan *eventListenerInfoEventChannel chan *Event
}// Start
//
//	@Author  zhaosy
//	@Description: 开始启动分发处理器
//	@date  2024-08-08 09:32:58
func (e *eventDispatcherManager) Start() {for {select {//发送事件case event := <-e.EventChannel:{//这里可以进行扩展,例如取消某个事件针对某个监听者分发fmt.Println("监听事件", event.EventName)//这里匹配是通过精确匹配,后期如果需要进行模糊匹配可以进行支持即可,例如前缀后缀这类的,进行扩展即可for _, listener := range e.listeners[event.EventName] {if event.AsyncHandle {//如果采用异步发布事件,事件顺序无法保证,也就是乱序,这里可以根据实际标志是否进行异步分发go listener(event) //通过协程进行处理} else {//默认采用同步方式进行分发事件listener(event)}}}//注册事件case register := <-e.RegisterChannel:{fmt.Println("注册事件", register.EventName)//进行注册e.dispatcher.listeners[register.EventName] = append(e.dispatcher.listeners[register.EventName], register.EventListener)fmt.Printf("注册事件结果:%#v", e.dispatcher.listeners)}//可以扩展取消事件}}}
  • 监听者注册器,通过包名直接注册
// RegisterListener
//
//	@Author  zhaosy
//	@Description: 注册事件
//	@date  2024-08-08 09:05:10
func RegisterListener(eventName string, listener EventListener) error {if eventName == "" {return fmt.Errorf("event name is empty")}if listener == nil {return fmt.Errorf("listener is nil")}e := &eventListenerInfo{EventName:     eventName,EventListener: listener,}//发送到注册链eventDispatcherManagerObj.RegisterChannel <- ereturn nil
}
  • 发送监听
// Send
//
//	@Author  zhaosy
//	@Description: 发生事件
//	@date  2024-08-08 09:05:29
func Send(event *Event) error {if event == nil {return fmt.Errorf("event is nil")}if event.EventName == "" {return fmt.Errorf("event name is empty")}eventDispatcherManagerObj.EventChannel <- eventreturn nil
}

测试:

func TestEvent(t *testing.T) {eventName := "test"events.RegisterListener(eventName, func(event *events.Event) {//这里建议使用goroutine进行异步处理业务,这样不会拖慢事件分发器分发效率// go dosomething(event)fmt.Println("第一个监听器", event.EventName, event.Data)})events.RegisterListener(eventName, func(event *events.Event) {fmt.Println("第二个监听器", event.EventName, event.Data)})//模拟发送事件消息for i := 0; i < 10; i++ {//走同步if i < 6 {events.Send(&events.Event{EventName: eventName,Data:      i,})} else {//走异步events.Send(&events.Event{AsyncHandle: true,EventName:   eventName,Data:        i,})}}time.Sleep(5 * time.Second)
}

结果:

相关文章:

go 事件机制(观察者设计模式)

背景&#xff1a; 公司目前有个业务&#xff0c;收到数据后&#xff0c;要分发给所有的客户端或者是业务模块&#xff0c;类似消息通知这样的需求&#xff0c;自然而然就想到了事件&#xff0c;观察者比较简单就自己实现以下&#xff0c;确保最小功能使用支持即可&#xff0c;其…...

RISC-V竞赛|第二届 RISC-V 软件移植及优化锦标赛报名正式开始!

目录 赛事背景 赛道方向 适配夺旗赛 优化竞速赛 比赛赛题&#xff08;总奖金池8万元&#xff01;&#xff09; &#x1f525;竞速赛 - OceanBase 移植与优化 比赛赛程&#xff08;暂定&#xff09; 赛事说明 「赛事背景」 为了推动 RISC-V 软件生态更快地发展&#xff0…...

【VTK】ubuntu手动编译VTK9.3 Generating qmltypes file 失败

环境 硬件&#xff1a;Jetson Xavier NX 套件 系统&#xff1a;Ubuntu 20.04 软件 &#xff1a;QT5.15.6 解决 0、问题 最近在Jetson Xavier NX 套件上编译VTK库&#xff0c;因为想要配合QQuick使用&#xff0c;所以cmake配置时勾选了VTK_MODULE_ENABLE_VTK_GUISupportQtQu…...

学习java的日子 Day64 学生管理系统 web2.0 web版本

MVC设计模式 概念 - 代码的分层 MVC&#xff1a;项目分层的思想 字母表示层理解MModle模型层业务的具体实现VView视图层展示数据CController控制器层控制业务流程&#xff08;跳转&#xff09; 1.细化理解层数 Controller&#xff1a;控制器层&#xff0c;用于存放Servlet&…...

【第14章】Spring Cloud之Gateway路由断言(IP黑名单)

文章目录 前言一、内置路由断言1. 案例&#xff08;Weight&#xff09;2. 更多断言 二、自定义路由断言1. 黑名单断言2. 全局异常处理3. 应用配置4. 单元测试 总结 前言 Spring Cloud Gateway可以让我们根据请求内容精确匹配到对应路由服务,官方已经内置了很多路由断言,我们也…...

3、pnpm yarn npm

项目里实际上就只有这些依赖 node module 里却有很多的包 原因&#xff1a; 比如说vue&#xff0c;vue内部有依赖了其余的包。工具又依赖了别的依赖 造成的问题&#xff1a;我可以直接去用这个包&#xff0c;但是这个包在package.json中却没有看到-----幽灵依赖 那如果说别…...

❄️5. Kubernetes核心资源之名称空间和Pod实战

**什么是名称空间Namespace: ** Namespace是k8s系统中的一种非常重要资源&#xff0c;它的主要作用是用来实现多套环境的资源隔离或者多用户的资源隔离。默认情况下&#xff0c;k8s集群中的所有的Pod都是可以相互访问的。但是在实际中&#xff0c;可能不想让两个Pod之间进行互…...

锂电池充电板电路设计

写这篇文章的目的主要是个人经验的总结&#xff0c;希望能给开发者们提供一种锂电池充电电路以及电源显示的电路思路。接下来从以下几个方面讲述电路。 设计这款电路的初衷是想用一块硬币大小的锂电池作为供电电源&#xff08;3.5V-4.2V&#xff09;&#xff0c;降压供给3.3V电…...

工业互联网产教融合实训基地解决方案

一、引言 随着“中国制造2025”战略的深入实施与全球工业4.0浪潮的兴起&#xff0c;工业互联网作为新一代信息技术与制造业深度融合的产物&#xff0c;正引领着制造业向智能化、网络化、服务化转型。为培养适应未来工业发展需求的高素质技术技能人才&#xff0c;构建工业互联网…...

高效批量提取PPT幻灯片中图片的方法

处理包含大量图片的PPT&#xff08;PowerPoint&#xff09;幻灯片已成为许多专业人士的日常任务之一。然而&#xff0c;手动从每张幻灯片中逐一提取图片不仅耗时耗力&#xff0c;还容易出错。为了提升工作效率&#xff0c;减少重复劳动&#xff0c;探索并实现一种高效批量提取P…...

怎么在 React Native 应用中处理深度链接?

深度链接是一种技术&#xff0c;其中给定的 URL 或资源用于在移动设备上打开特定页面或屏幕。因此&#xff0c;深度链接可以引导用户到应用程序内的特定屏幕&#xff0c;而不仅仅是启动移动设备上的应用程序&#xff0c;从而提供更好的用户体验。这个特定的屏幕可能位于一系列层…...

el-table自动滚动到最底部

我的需求是这样的&#xff0c;因为我的表格是动态的&#xff0c;可以手动新增行&#xff0c;固定表头&#xff0c;而且需要一屏显示&#xff0c;为了方便用户就需要再新增的时候表格自动向上滚动。 差了官方文档后发现有一个属性可以支持 这个属性正是自己需要的&#xff0c;所…...

小白零基础学数学建模系列-引言与课程目录

目录 引言一、我们的专辑包含哪些内容&#xff1f;第一周&#xff1a;数学建模基础与工具第二周&#xff1a;高级数学建模技巧与应用第三周&#xff1a;机器学习基础与数据处理第四周&#xff1a;监督学习与无监督学习算法第五周&#xff1a;神经网络 二、学完本专辑能收获到什…...

Integer类型比较是 == 还是equals()

在Java编程中&#xff0c;判断两个Integer对象是否相等时&#xff0c;我们经常遇到使用和equals()方法的选择问题。这两个操作符和方法在判断对象相等性时有所不同&#xff0c;理解它们的区别对于编写健壮的代码至关重要。 使用判断Integer相等性 在Java中&#xff0c;操作符…...

七夕情人节送什么礼物?看完这篇你就知道了

在这个充满爱意的时刻&#xff0c;送上一份精心挑选的礼物&#xff0c;不仅能表达你的爱意&#xff0c;更能加深彼此之间的情感联系。然而&#xff0c;选择一份合适的情人节礼物并非易事&#xff0c;因为每个人都有其独特的需求和喜好。如果你还在为情人节送什么礼物而纠结&…...

让B站直接变成一个纯粹的音乐平台的简单小方法

可能在大多数人眼里&#xff0c;B站就是一个内容丰富的高质量视频平台 但实际上B站还是一个“音乐平台”&#xff0c;只不过大多数时候都是以视频的形式呈现&#xff0c;所以你们可能对此没啥感觉。 那么今天给大家分享一款神级插件&#xff0c;让B站变成一个纯粹的音乐平台&a…...

【MySQL 01】在 Ubuntu 22.04 环境下安装 MySQL

文章目录 &#x1f308; 1. 说明&#x1f308; 2. 卸载不必要的环境&#x1f308; 3. 安装 MySQL&#x1f308; 4. 启动和关闭 MySQL 服务&#x1f308; 5. 临时登录 MySQL&#x1f308; 6. 设置 MySQL 密码&#x1f308; 7. 配置 MySQL &#x1f308; 1. 说明 在安装与卸载中…...

linux命令 根据某一字段去掉txt中重复的数据

前提&#xff1a; 文档为格式化好的数据。比如一行是一个json。 判断总共有多少行数据&#xff1a; grep No f.txt | wc -l 查询重复数据有多少行&#xff1a; grep No f.txt | sort -u | wc -l 找到重复的那行数据&#xff1a;(如果每行的json数据大&#xff0c;可忽略此操…...

LVS(Linux virual server)

一&#xff1a;环境准备&#xff1a; rhel9 软件&#xff1a;httpd&#xff0c; ipvsadm 四台纯净的rhel9机子&#xff1a;一台LVS调度设备&#xff08;双网卡&#xff09;&#xff0c;两台webserver&#xff08;单网卡仅主机&#xff09;&#xff0c;一台客户机 DR模式多…...

End-to-End Object Detection with Transformers(Detection Transformer)翻译

摘要 我们提出了一种新方法&#xff0c;将目标检测视为直接的集合预测问题。我们的方法简化了检测流程&#xff0c;有效消除了对许多手工设计组件的需求&#xff0c;如非极大值抑制过程或锚框生成&#xff0c;这些组件显式编码了我们对任务的先验知识。新框架称为检测变换器&a…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...