1
0
mirror of https://github.com/tmrts/go-patterns.git synced 2024-11-25 14:36:06 +03:00

Add fan-in/out messaging patterns

This commit is contained in:
Tamer Tas 2016-01-18 19:01:39 +02:00
parent 4f4ceb2dc1
commit a8f8670c1e
2 changed files with 73 additions and 0 deletions

33
fan/fan_in.go Normal file
View File

@ -0,0 +1,33 @@
package fan
import "sync"
// In implements fan.In messaging pattern
// Merges different channels in one channel
func In(cs ...<-chan int) <-chan int {
var wg sync.WaitGroup
out := make(chan int)
// Start an send goroutine for each input channel in cs. send
// copies values from c to out until c is closed, then calls wg.Done.
send := func(c <-chan int) {
for n := range c {
out <- n
}
wg.Done()
}
wg.Add(len(cs))
for _, c := range cs {
go send(c)
}
// Start a goroutine to close out once all the send goroutines are
// done. This must start after the wg.Add call.
go func() {
wg.Wait()
close(out)
}()
return out
}

40
fan/fan_out.go Normal file
View File

@ -0,0 +1,40 @@
package fan
// Out implements fan.Out messaging pattern
// Split a channel into n channels that receive messages
// in a round-robin fashion.
func Out(ch <-chan int, n int) []<-chan int {
cs := make([]chan int)
for i := 0; i < n; i++ {
cs = append(cs, make(chan int))
}
// Distributes the work in a round robin fashion among the stated number
// of channels until the main channel has been closed. In that case, close
// all channels and return.
distributeToChannels := func(ch <-chan int, cs []chan<- int) {
// Close every channel when the execution ends.
defer func(cs []chan<- int) {
for _, c := range cs {
close(c)
}
}(cs)
for {
for _, c := range cs {
select {
case val, ok := <-ch:
if !ok {
return
}
c <- val
}
}
}
}
go distributeToChannels(ch, cs)
return cs
}