go并发模式之----发布订阅模式

常见模式之五:发布订阅模式

定义

顾名思义,就是有个发布者,和多个订阅者,发布者发布一条消息,订阅者都能收到并行处理

使用场景

  • 适用于需要解耦、并发处理和可扩展性的场景

  • 提供了一种灵活的机制,允许多个订阅者独立地处理事件或消息

  • 比如事件驱动系统、消息队列等等

示例

假设有个场景:我们支付完成后,需要做三件事

  • 更新订单状态

  • 发送站内信

  • 更新商品销量

代码如下:

Go 复制代码
package main

import (
	"fmt"
	"sync"
)

// EventData 发布数据
type EventData struct {
	Data interface{}
}

// Subscriber 关注者
type Subscriber struct {
	UniqueFlag string
	HandleFunc func(EventData)
}

// Publisher 发布者
type Publisher struct {
	SubDict map[string]*Subscriber
	mutex   *sync.Mutex
}

// NewPublisher 初始化发布者
func NewPublisher() *Publisher {
	return &Publisher{
		SubDict: make(map[string]*Subscriber),
		mutex:   &sync.Mutex{},
	}
}

// AddSubscriber 添加订阅
func (p *Publisher) AddSubscriber(s *Subscriber) {
	p.mutex.Lock()
	defer p.mutex.Unlock()
	p.SubDict[s.UniqueFlag] = s
}

// DelSubscriber 移除订阅
func (p *Publisher) DelSubscriber(s *Subscriber) {
	p.mutex.Lock()
	defer p.mutex.Unlock()
	delete(p.SubDict, s.UniqueFlag)
}

// Publish 发布消息
func (p *Publisher) Publish(ed EventData) {
	p.mutex.Lock()
	defer p.mutex.Unlock()
	wg := &sync.WaitGroup{}
	for _, s := range p.SubDict {
		wg.Add(1)
		go func(sub *Subscriber) {
			defer wg.Done()
			sub.HandleFunc(ed)
		}(s)
	}
	wg.Wait()
}

func main() {
	p := NewPublisher()
	// 调用支付后
	// 1.更改订单状态
	// 2.发送站内信
	// 3.商品销售量+1
	p.AddSubscriber(
		&Subscriber{
			UniqueFlag: "orderUpdate",
			HandleFunc: func(data EventData) {
				fmt.Println("更改订单状态 ", data)
			},
		})
	p.AddSubscriber(
		&Subscriber{
			UniqueFlag: "msgSend",
			HandleFunc: func(data EventData) {
				fmt.Println("发送站内信 ", data)
			},
		})
	p.AddSubscriber(
		&Subscriber{
			UniqueFlag: "saleUpdate",
			HandleFunc: func(data EventData) {
				fmt.Println("商品销售量+1 ", data)
			},
		})
	p.Publish(EventData{
		Data: struct {
			SaleId   int
			UserId   int
			SaleName string
		}{
			SaleId:   123,
			UserId:   456,
			SaleName: "华为meta60pro",
		},
	})
}

打印结果:

发送站内信 {{123 456 华为meta60pro}}

商品销售量+1 {{123 456 华为meta60pro}}

更改订单状态 {{123 456 华为meta60pro}}

相关推荐
IT_10241 小时前
Spring Boot项目开发实战销售管理系统——系统设计!
大数据·spring boot·后端
ai小鬼头2 小时前
AIStarter最新版怎么卸载AI项目?一键删除操作指南(附路径设置技巧)
前端·后端·github
Touper.2 小时前
SpringBoot -- 自动配置原理
java·spring boot·后端
黄雪超3 小时前
JVM——函数式语法糖:如何使用Function、Stream来编写函数式程序?
java·开发语言·jvm
ThetaarSofVenice3 小时前
对象的finalization机制Test
java·开发语言·jvm
思则变3 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
一只叫煤球的猫3 小时前
普通程序员,从开发到管理岗,为什么我越升职越痛苦?
前端·后端·全栈
一只鹿鹿鹿3 小时前
信息化项目验收,软件工程评审和检查表单
大数据·人工智能·后端·智慧城市·软件工程
lijingguang3 小时前
在C#中根据URL下载文件并保存到本地,可以使用以下方法(推荐使用现代异步方式)
开发语言·c#
专注VB编程开发20年4 小时前
开机自动后台运行,在Windows服务中托管ASP.NET Core
windows·后端·asp.net