Go基于观察者模式实现的订阅/发布
面UCloud的时候问到了这题,下来看了一下是基于观察者模式实现的,仅作记录
/**
* @Author: lzw5399
* @Date: 2021/5/20 20:38
* @Desc: 基于观察者模式实现的订阅发布
*/
package main
import (
"errors"
"fmt"
"sync"
)
func main() {
server := NewServer()
server.Subscribe("CCTV1", NewBasicClient("张三"))
server.Subscribe("CCTV2", NewBasicClient("张三"))
server.Subscribe("CCTV1", NewBasicClient("李四"))
server.Publish("CCTV1", "开播辣!")
}
// ---server---
type Server struct {
Topics map[string]*Topic // k=topicName v=topic
sync.RWMutex
}
func NewServer() *Server {
return &Server{
Topics: make(map[string]*Topic),
RWMutex: sync.RWMutex{},
}
}
func (s *Server) Subscribe(topicName string, client Client) {
s.RLock()
topic, exist := s.Topics[topicName]
s.RUnlock()
// 存在topic直接添加client
if exist {
topic.AddClient(client)
return
}
// 不存在topic,新建topic,在添加client
topic = NewTopic(topicName)
topic.AddClient(client)
s.Lock()
s.Topics[topicName] = topic
s.Unlock()
}
func (s *Server) Publish(topicName string, message string) error {
s.RLock()
topic, exist := s.Topics[topicName]
s.RUnlock()
if exist {
topic.Notify(message)
return nil
}
return errors.New("当前topic不存在")
}
// ---end server---
// ---topic---
type Topic struct {
Name string
clients map[string]Client // k=clientName v=client
sync.RWMutex
}
func NewTopic(name string) *Topic {
return &Topic{
Name: name,
clients: make(map[string]Client),
RWMutex: sync.RWMutex{},
}
}
func (t *Topic) AddClient(client Client) {
// 只添加存在的
if _, exist := t.clients[client.Name()]; !exist {
t.Lock()
t.clients[client.Name()] = client
t.Unlock()
}
}
func (t *Topic) Notify(message string) {
for _, v := range t.clients {
v.ConsumeCallback(message)
}
}
// ---end topic---
// ---client---
type Client interface {
Name() string
ConsumeCallback(message string)
}
type BasicClient struct {
name string
}
func NewBasicClient(name string) *BasicClient {
return &BasicClient{
name: name,
}
}
func (b *BasicClient) Name() string {
return b.name
}
func (b *BasicClient) ConsumeCallback(message string) {
fmt.Printf("当前Client: %s, 接收到的消息为: %s\n", b.Name(), message)
}
// ---end client---
Go基于观察者模式实现的订阅/发布的更多相关文章
- 基于Redis消息的订阅发布应用场景
目录 基于Redis消息的订阅发布应用场景 1.应用背景 2.困境 2.1 锁表风险 2.2 实时性差 2.3 增加编程复杂性 2.4 实时效果 3.解决方案 3.1 前端传值给服务端 3.2 服务端 ...
- 基于Redis的消息订阅/发布
在工业生产设计中,我们往往需要实现一个基于消息订阅的模式,用来对非定时的的消息进行监听订阅. 这种设计模式在 总线设计模式中得到体现.微软以前的WCF中实现了服务总线 ServiceBus的设计模式. ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布
之前的章节我们介绍了如何通过dapr发起一个服务调用,相信看过前几章的小伙伴已经对dapr有一个基本的了解了,今天我们来聊一聊dapr的另外一个功能--订阅发布 目录:一.通过Dapr实现一个简单的基 ...
- 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载
一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...
- 基于.NET Socket Tcp的发布-订阅框架
基于.NET Socket Tcp的发布-订阅框架 一.分布式消息总线 在很多MIS项目之中都有这样的需求,需要一个及时.高效的的通知机制,即比如当使用者A完成了任务X,就需要立即告知使用者B任务X已 ...
- 基于Http协议订阅发布系统设计
基于Http协议订阅发布系统设计 --物联网系统架构设计 1,订阅发布(subscriber-publisher) 订阅发布模式最典型的应用场景就是消息系统的设计.在消息系统的架构中 ...
- Java里观察者模式(订阅发布模式)
创建主题(Subject)接口 创建订阅者(Observer)接口 实现主题 实现观察者 测试 总结 在公司开发项目,如果碰到一些在特定条件下触发某些逻辑操作的功能的实现基本上都是用的定时器 比如用户 ...
- 基于redis的消息订阅与发布
Redis 的 SUBSCRIBE 命令可以让客户端订阅任意数量的频道, 每当有新信息发送到被订阅的频道时, 信息就会被发送给所有订阅指定频道的客户端. 作为例子, 下图展示了频道 channel1 ...
- 基于观察者模式-----otto源码分析
一.otto简介 otto是支付公司square一个专注于android的开源项目,该项目是一个event bus模式的消息框架,是一个基于Guava的增强型事件总线.旨在将应用程序的不同部分分离,同 ...
- ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现
ASP.NET MVC 学习笔记-2.Razor语法 1. 表达式 表达式必须跟在“@”符号之后, 2. 代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...
随机推荐
- RocketMQ 5.0 多语言客户端的设计与实现
本文作者:古崟佑,阿里云中间件开发. RocketMQ 5.0 版本拥有非常多新特性,比如存储计算分离. batch 能力的提升等,它是具有里程碑意义的版本. 提到新版本,我们往往会首先想到服务端架构 ...
- Newstar_week1-2_wp
week1 wp crypto 一眼秒了 n费马分解再rsa flag: import libnum import gmpy2 from Crypto.Util.number import * p = ...
- Redhat 7.6安装11G RAC GI时遇到此类报错
环境:Redhat Linux 7.6 + Oracle 11.2.0.4 RAC 现象:图像化安装过程中,按照提示执行root.sh脚本,报错中断. 1. 具体现象 2. 定位问题 3. 解决问题 ...
- Linux运行时动态库搜索路径优先级
Windows运行时动态库搜索路径优先级: 在Windows运行时,动态库(通常指DLL文件)的搜索路径遵循一定的优先级顺序,以确保程序能够正确地加载所需的动态库.以下是对Windows运行时动态库搜 ...
- Go语言学习 _基础03 _数组和切片
Go语言学习 _基础03 _数组和切片 1.数组 package array_test import "testing" func TestArrayInit(t *testing ...
- 【总结】线性dp的几种重要模型
当前点定义 \(f[i]\) :走到第 \(i\) 个点的方案数 / 最值. \(f[i][j]\) :走到第 \(i\) 个点,选了 \(j\) 个的答案. 依据题目的限制个数可以继续添加维数,也可 ...
- 5.5 Vim移动光标命令汇总
Vim 文本编辑器中,最简单的移动光标的方式是使用方向键,但这种方式的效率太低,更高效的方式使用快捷键. Vim 移动光标常用的快捷键及其功能如下面各表所示,需要注意的是,表中所有的快捷键都在命令模式 ...
- 使用 C# 入门深度学习:线性代数
教程名称:使用 C# 入门深度学习 作者:痴者工良 地址: https://torch.whuanle.cn 线性代数 目录 线性代数 推荐书籍 基础知识 标量.向量.矩阵 Pytorch 的一些数学 ...
- 两个新出的 JavaScript 运算符
在 ECMAScript 2021(ES12)中,JavaScript 引入了新的逻辑赋值操作符 &&= 和 ??=.这些操作符将逻辑运算符与赋值运算符相结合,提供了更加简洁.直观的赋 ...
- MindSpore-2.4版本中的一些新特性
技术背景 在前面的一篇博客中我们介绍了MindSpore-2.4-gpu的安装和其中可能出现的一些问题.这里我们在安装完成之后,可以尝试使用一些MindSpore新版本的特性.那么在安装之后,如果是使 ...