A very simple example of using a map of channels for pub/sub in go.
To run it go here http://play.golang.org/p/eXwppMgHR3
A very simple example of using a map of channels for pub/sub in go.
To run it go here http://play.golang.org/p/eXwppMgHR3
package main | |
import ( | |
"fmt" | |
"time" | |
) | |
func main() { | |
pub1 := make(chan string) | |
pub2 := make(chan string) | |
sub1 := make(chan string) | |
sub2 := make(chan string) | |
sub3 := make(chan string) | |
go listen("Subscriber 1", sub1) | |
go listen("Subscriber 2", sub2) | |
go listen("Subscriber 3", sub3) | |
subscriptions := map[chan string][]chan string{ | |
pub1: []chan string{sub1, sub2}, | |
pub2: []chan string{sub2, sub3}, | |
} | |
go publish(subscriptions) | |
pub1 <- "Hello, World!" | |
pub2 <- "Hi, Universe!" | |
pub1 <- "Goodbye, Cruel World!" | |
subscriptions[pub1] = append(subscriptions[pub1], sub3) | |
pub1 <- "Just kidding!" | |
time.Sleep(2 * time.Second) | |
} | |
func listen(name string, subscriber chan string) { | |
for { | |
select { | |
case message := <-subscriber: | |
fmt.Printf("%q: %q\n", name, message) | |
case <-time.After(time.Millisecond): | |
} | |
} | |
} | |
func publish(subscriptions map[chan string][]chan string) { | |
for { | |
for publisher, subscribers := range subscriptions { | |
select { | |
case message := <-publisher: | |
for _, subscriber := range subscribers { | |
subscriber <- message | |
} | |
case <-time.After(time.Millisecond): | |
} | |
} | |
} | |
} |
case <-time.After(time.Millisecond):
this line makes high CPU usage
This would be better suited for Ruby.
This is a fantastic example, and very thought provoking.
But, if you choose to use something like this, don't ignore that this will trigger the race condition detector on this line:
subscriptions[pub1] = append(subscriptions[pub1], sub3)