Skip to content

Instantly share code, notes, and snippets.

@nicolasparada
Last active July 27, 2018 06:51
Show Gist options
  • Select an option

  • Save nicolasparada/9896c13ab08c68e1e59f876c29ad8263 to your computer and use it in GitHub Desktop.

Select an option

Save nicolasparada/9896c13ab08c68e1e59f876c29ad8263 to your computer and use it in GitHub Desktop.
Golang PubSub
package pubsub
import (
"reflect"
"sync"
)
// PubSub system.
type PubSub interface {
// Pub publishes to the given topic.
Pub(topic string, v interface{})
// Sub subscribes the channel to the given topic.
Sub(topic string, ch interface{}) (unsub func())
}
type pubSub struct {
clients sync.Map
}
type client struct {
topic string
chVal reflect.Value
}
// New creates a PubSub implementation.
func New() PubSub {
return new(pubSub)
}
func (ps *pubSub) Pub(topic string, v interface{}) {
val := reflect.ValueOf(v)
ps.clients.Range(func(key, _ interface{}) bool {
c := key.(*client)
if c.topic == topic {
c.chVal.Send(val)
}
return true
})
}
func (ps *pubSub) Sub(topic string, ch interface{}) func() {
chVal := reflect.ValueOf(ch)
if chVal.Kind() != reflect.Chan {
panic("pubsub: ch is the wrong type")
}
c := &client{topic, chVal}
ps.clients.Store(c, nil)
return func() {
ps.clients.Delete(c)
}
}
@nicolasparada
Copy link
Copy Markdown
Author

nicolasparada commented May 31, 2018

Ex:

func main() {
	ps := pubsub.New()

	events := make(chan string)
	defer close(events)
	defer ps.Sub("events", events)()

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()
		ps.Pub("events", "hello there")
	}()

	go func() {
		defer wg.Done()
		fmt.Println("event:", <-events)
	}()

	wg.Wait()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment