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:
parent
4f4ceb2dc1
commit
a8f8670c1e
33
fan/fan_in.go
Normal file
33
fan/fan_in.go
Normal 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
40
fan/fan_out.go
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user