Hi were you talking about something like this? I used channels over 
callbacks.
I quickly prototyped it. Is this approach better or we have to do 
improvements?

package main

import (
"fmt"
"math/rand"
"sync"
"time"
)

type Data struct {
data interface{}
topic string
}

type ChannelSlice []chan Data

type EventBus struct {
subscribers map[string] ChannelSlice
rm sync.RWMutex
}

func (eb *EventBus)publish(topic string, data interface{}) {
eb.rm.RLock()
if ch, found := eb.subscribers[topic]; found {
go _boradcastEvent(Data{data: data, topic:topic}, ch)
}
eb.rm.RUnlock()
}

func _boradcastEvent(data Data, sl ChannelSlice)  {
for _, ch := range sl {
ch <- data
}
}

func (eb *EventBus)subscribe(topic string, ch chan Data)  {
eb.rm.Lock()
if prev, found := eb.subscribers[topic]; found {
eb.subscribers[topic] = append(prev, ch)
} else {
eb.subscribers[topic] = append([] chan Data{}, ch)
}
eb.rm.Unlock()
}

var eb = &EventBus{
subscribers: map[string]ChannelSlice{},
}

func printData(ch string, data Data)  {
fmt.Printf("Channel: %s; Topic: %s; Data: %v\n", ch, data.topic, data.data)
}

func publisTo(topic string, data string)  {
for {
eb.publish(topic, data)
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
}
}

func main()  {
ch1 := make(chan Data)
ch2 := make(chan Data)
ch3 := make(chan Data)

eb.subscribe("topic1", ch1)
eb.subscribe("topic2", ch2)
eb.subscribe("topic2", ch3)

go publisTo("topic1", "Hi topic 1")
go publisTo("topic2", "Welcome to topic 2")

for {
select {
case d := <-ch1:
go printData("ch1", d)
case d := <-ch2:
go printData("ch2", d)
case d := <-ch3:
go printData("ch3", d)
}
}
}




On Monday, March 11, 2019 at 10:29:33 AM UTC+5:30, Marcin Romaszewicz wrote:
>
> Channels are producer/consumer queues, they don't handle one to many 
> broadcasting, you'd need one channel per subscriber then you'd queue the 
> message to each of them. In my opinion, they work more nicely than 
> callbacks, since your handler can run in its own execution context, and not 
> in the callback invoker's execution context. They are really nice for round 
> robin between multiple receivers, though.
>
> Why write it yourself? Check out the Go bindings for Zeromq 
> <http://zeromq.org/bindings:go>, which supports pub-sub in exactly the 
> way you mention. I've used this thing in production to route > 200,000 
> pub/sub messages per second. It may be overkill if you're within a single 
> process, though.
>
> -- Marcin
>
>
> On Sun, Mar 10, 2019 at 9:41 PM Kasun Vithanage <alan...@gmail.com 
> <javascript:>> wrote:
>
>> Hi all,
>>
>> I've experience implementing event buses in Java. 
>> In Java, I used a singleton where I can register callbacks to methods and 
>> fire event from a publisher(maybe from another thread) and propagate it to 
>> subscribers.
>>
>> In Go what would be the best pattern to implement a pub/sub event bus? 
>> Are channels are a better choice than using callbacks in this scenario(*one 
>> to many* event propagation)?
>> Or callbacks are better for this? 
>>
>> (I need to propagate events *only* to subscribers of the topic)
>>
>> Regards,
>> Kasun
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to