Skip to content

Instantly share code, notes, and snippets.

@rightfold
Created June 18, 2015 07:30
Show Gist options
  • Save rightfold/2011e40f6e9fb3ff8fb5 to your computer and use it in GitHub Desktop.
Save rightfold/2011e40f6e9fb3ff8fb5 to your computer and use it in GitHub Desktop.
Publish–subscribe in Go
package main
import (
"fmt"
"sync"
"time"
)
type Publisher struct {
mutex sync.RWMutex
subscribers map[chan<- interface{}]bool
closed bool
}
func New() *Publisher {
return &Publisher{
subscribers: make(map[chan<- interface{}]bool),
closed: false,
}
}
func (p *Publisher) Close() {
p.mutex.Lock()
defer p.mutex.Unlock()
for subscriber := range p.subscribers {
close(subscriber)
}
p.closed = true
}
func (p *Publisher) Publish(value interface{}) {
p.mutex.RLock()
defer p.mutex.RUnlock()
if p.closed {
panic("publish on closed publisher")
}
for subscriber := range p.subscribers {
subscriber <- value
}
}
func (p *Publisher) Subscribe(s chan<- interface{}) {
p.mutex.Lock()
defer p.mutex.Unlock()
p.subscribers[s] = true
}
func (p *Publisher) Unsubscribe(s chan<- interface{}) {
p.mutex.Lock()
defer p.mutex.Unlock()
delete(p.subscribers, s)
}
func main() {
publisher := New()
for i := 0; i < 5; i++ {
go func() {
c := make(chan interface{})
publisher.Subscribe(c)
defer publisher.Unsubscribe(c)
for x := range c {
fmt.Println(x.(int))
}
fmt.Println("done!")
}()
}
time.Sleep(time.Second)
for i := 0; i < 5; i++ {
publisher.Publish(i)
}
publisher.Close()
time.Sleep(time.Second)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment