zoukankan      html  css  js  c++  java
  • 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)
    	}
    }
    

      

  • 相关阅读:
    音频player
    重要 sdl音最简
    sdl win 播放video hello--
    linux里helloworld
    0129 总结Cygwin要用这个,不要用mingw,根本下不下来
    转音视频重要
    Gradle项目无法下载jar包 修改 插件下载地址plugins.gradle.org

    开源gradle**all.zip下载慢问题
    [Effective Java] 第1条 考虑用静态工厂方法代替构造函数
  • 原文地址:https://www.cnblogs.com/zyfeng/p/15698841.html
Copyright © 2011-2022 走看看