• Golang订阅者模式


    代码

    package pubsub
    
    import (
    	"sync"
    	"time"
    )
    
    type (
    	subscriber chan interface{}         // 订阅者管道
    	topicFunc  func(v interface{}) bool // 主题过滤器
    )
    
    // 发布者对象
    type Publisher struct {
    	m           sync.RWMutex             // 读写锁
    	buffer      int                      // 订阅队列缓存大小
    	timeout     time.Duration            // 发布超时时间
    	subscribers map[subscriber]topicFunc // 订阅者信息
    }
    
    // 构建发布者对象 设置发布超时时间和缓存队列长度
    func NewPublisher(publishTimeout time.Duration, buffer int) *Publisher {
    	return &Publisher{
    		buffer:      buffer,
    		timeout:     publishTimeout,
    		subscribers: make(map[subscriber]topicFunc),
    	}
    }
    
    // 添加订阅者 订阅全部主题
    func (this *Publisher) Subscribe() chan interface{} {
    	return this.SubscribeTopic(nil)
    }
    
    // 添加新订阅者 订阅过滤器筛选后的主题
    func (this *Publisher) SubscribeTopic(topic topicFunc) chan interface{} {
    	ch := make(chan interface{}, this.buffer)
    	this.m.Lock()
    	this.subscribers[ch] = topic
    	this.m.Unlock()
    	return ch
    }
    
    // 退出订阅
    func (this *Publisher) Evict(sub chan interface{}) {
    	this.m.Lock()
    	defer this.m.Unlock()
    
    	delete(this.subscribers, sub)
    	close(sub)
    }
    
    // 发布一个主题
    func (this *Publisher) Publish(v interface{}) {
    	this.m.RLock()
    	defer this.m.RUnlock()
    
    	var wg sync.WaitGroup
    	for sub, topic := range this.subscribers {
    		wg.Add(1)
    		go this.sendTopic(sub, topic, v, &wg)
    	}
    	wg.Wait()
    }
    
    // 发送主题(可以容忍一定超时)
    func (this *Publisher) sendTopic(sub subscriber, topic topicFunc, v interface{}, wg *sync.WaitGroup) {
    	defer wg.Done()
    	if topic != nil && !topic(v) {
    		return
    	}
    
    	select {
    	case sub <- v:
    	case <-time.After(this.timeout):
    	}
    }
    
    // 关闭发布者对象 同时关闭所有订阅者管道
    func (this *Publisher) Close() {
    	this.m.Lock()
    	defer this.m.Unlock()
    
    	for sub := range this.subscribers {
    		delete(this.subscribers, sub)
    		close(sub)
    	}
    }
    

      

  • 相关阅读:
    Linux 之dhcp服务搭建
    常用网络指令
    图解:光缆、终端盒、尾纤的作用和接法
    Excel2007给表格设置成只读加密属性 让他人无法修改
    CentOS 安裝 VMware Workstation / VMware Player
    Linux 命令之 grep
    iOS开发UI篇—从代码的逐步优化看MVC
    iOS开发UI篇—字典转模型
    iOS开发UI篇—九宫格坐标计算
    iOS开发UI篇—懒加载
  • 原文地址:https://www.cnblogs.com/zyfeng/p/15698841.html
Copyright © 2020-2023  润新知