mirror of
https://github.com/crazybber/go-pattern-examples.git
synced 2024-11-25 05:06:03 +03:00
add a fanout_in pattern
from : https://github.com/abour/concurrency/blob/master/main.go
This commit is contained in:
parent
9c2d2ddd43
commit
d0cc207d54
276
gomore/05_fan_out/fan_out_in.go
Normal file
276
gomore/05_fan_out/fan_out_in.go
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
package fanout
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func run() {
|
||||||
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||||
|
defer cancelFunc()
|
||||||
|
var errcList []chan error
|
||||||
|
|
||||||
|
// res := fanin(fanout(generateNumbers(ctx), squareNumbers))
|
||||||
|
|
||||||
|
nChan, errc, err := generateNumbers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
errcList = append(errcList, errc)
|
||||||
|
|
||||||
|
fChanl, errcl, err := fanout(ctx, nChan, squareNumbers)
|
||||||
|
errcList = append(errcList, errcl...)
|
||||||
|
|
||||||
|
res, errRes, err := fanin(fChanl, errcl)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case r := <-res:
|
||||||
|
v, ok := r.(int)
|
||||||
|
if !ok {
|
||||||
|
// TODO
|
||||||
|
_ = ok
|
||||||
|
}
|
||||||
|
fmt.Println(v)
|
||||||
|
case e := <-errRes:
|
||||||
|
fmt.Println(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Println("finished")
|
||||||
|
time.Sleep(10 * time.Duration(time.Second))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Op func(context.Context, chan interface{}) (chan interface{}, chan error, error)
|
||||||
|
|
||||||
|
func generateNumbers(ctx context.Context) (chan interface{}, chan error, error) {
|
||||||
|
fmt.Println("generateNumbers called")
|
||||||
|
out := make(chan interface{}, 100)
|
||||||
|
errc := make(chan error, 100)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(out)
|
||||||
|
defer close(errc)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
fmt.Println("gen: ", i)
|
||||||
|
out <- i
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out, errc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fanout(ctx context.Context, in chan interface{}, fct Op) ([]chan interface{}, []chan error, error) {
|
||||||
|
fmt.Println("fanout called")
|
||||||
|
var out []chan interface{}
|
||||||
|
var errcl []chan error
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
res, errc, err := fct(ctx, in)
|
||||||
|
// Todo: manage error
|
||||||
|
_ = err
|
||||||
|
out = append(out, res)
|
||||||
|
errcl = append(errcl, errc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, errcl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func squareNumbers(ctx context.Context, in chan interface{}) (chan interface{}, chan error, error) {
|
||||||
|
fmt.Println("squareNumbers called")
|
||||||
|
out := make(chan interface{}, 100)
|
||||||
|
errc := make(chan error, 100)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for v := range in {
|
||||||
|
num, _ := v.(int)
|
||||||
|
|
||||||
|
squared := num * num
|
||||||
|
|
||||||
|
select {
|
||||||
|
case out <- squared:
|
||||||
|
case <-ctx.Done():
|
||||||
|
fmt.Println("ctx done")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(out)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out, errc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fanin(ins []chan interface{}, errcl []chan error) (chan interface{}, chan error, error) {
|
||||||
|
fmt.Println("fanin called")
|
||||||
|
out := make(chan interface{}, 100)
|
||||||
|
errcout := make(chan error, 100)
|
||||||
|
var waitgroup sync.WaitGroup
|
||||||
|
|
||||||
|
length := len(ins) + len(errcl)
|
||||||
|
waitgroup.Add(length)
|
||||||
|
|
||||||
|
for _, v := range ins {
|
||||||
|
go func(w chan interface{}) {
|
||||||
|
for val := range w {
|
||||||
|
out <- val
|
||||||
|
}
|
||||||
|
waitgroup.Done()
|
||||||
|
}(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range errcl {
|
||||||
|
go func(errc chan error) {
|
||||||
|
for v := range errc {
|
||||||
|
errcout <- v
|
||||||
|
}
|
||||||
|
waitgroup.Done()
|
||||||
|
}(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
waitgroup.Wait()
|
||||||
|
close(out)
|
||||||
|
close(errcout)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out, errcout, nil
|
||||||
|
}
|
||||||
|
func main() {
|
||||||
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||||
|
defer cancelFunc()
|
||||||
|
var errcList []chan error
|
||||||
|
|
||||||
|
// res := fanin(fanout(generateNumbers(ctx), squareNumbers))
|
||||||
|
|
||||||
|
nChan, errc, err := generateNumbers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
errcList = append(errcList, errc)
|
||||||
|
|
||||||
|
fChanl, errcl, err := fanout(ctx, nChan, squareNumbers)
|
||||||
|
errcList = append(errcList, errcl...)
|
||||||
|
|
||||||
|
res, errRes, err := fanin(fChanl, errcl)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case r := <-res:
|
||||||
|
v, ok := r.(int)
|
||||||
|
if !ok {
|
||||||
|
// TODO
|
||||||
|
_ = ok
|
||||||
|
}
|
||||||
|
fmt.Println(v)
|
||||||
|
case e := <-errRes:
|
||||||
|
fmt.Println(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Println("finished")
|
||||||
|
time.Sleep(10 * time.Duration(time.Second))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Op func(context.Context, chan interface{}) (chan interface{}, chan error, error)
|
||||||
|
|
||||||
|
func generateNumbers(ctx context.Context) (chan interface{}, chan error, error) {
|
||||||
|
fmt.Println("generateNumbers called")
|
||||||
|
out := make(chan interface{}, 100)
|
||||||
|
errc := make(chan error, 100)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(out)
|
||||||
|
defer close(errc)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
fmt.Println("gen: ", i)
|
||||||
|
out <- i
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out, errc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fanout(ctx context.Context, in chan interface{}, fct Op) ([]chan interface{}, []chan error, error) {
|
||||||
|
fmt.Println("fanout called")
|
||||||
|
var out []chan interface{}
|
||||||
|
var errcl []chan error
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
res, errc, err := fct(ctx, in)
|
||||||
|
// Todo: manage error
|
||||||
|
_ = err
|
||||||
|
out = append(out, res)
|
||||||
|
errcl = append(errcl, errc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, errcl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func squareNumbers(ctx context.Context, in chan interface{}) (chan interface{}, chan error, error) {
|
||||||
|
fmt.Println("squareNumbers called")
|
||||||
|
out := make(chan interface{}, 100)
|
||||||
|
errc := make(chan error, 100)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for v := range in {
|
||||||
|
num, _ := v.(int)
|
||||||
|
|
||||||
|
squared := num * num
|
||||||
|
|
||||||
|
select {
|
||||||
|
case out <- squared:
|
||||||
|
case <-ctx.Done():
|
||||||
|
fmt.Println("ctx done")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(out)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out, errc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fanin(ins []chan interface{}, errcl []chan error) (chan interface{}, chan error, error) {
|
||||||
|
fmt.Println("fanin called")
|
||||||
|
out := make(chan interface{}, 100)
|
||||||
|
errcout := make(chan error, 100)
|
||||||
|
var waitgroup sync.WaitGroup
|
||||||
|
|
||||||
|
length := len(ins) + len(errcl)
|
||||||
|
waitgroup.Add(length)
|
||||||
|
|
||||||
|
for _, v := range ins {
|
||||||
|
go func(w chan interface{}) {
|
||||||
|
for val := range w {
|
||||||
|
out <- val
|
||||||
|
}
|
||||||
|
waitgroup.Done()
|
||||||
|
}(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range errcl {
|
||||||
|
go func(errc chan error) {
|
||||||
|
for v := range errc {
|
||||||
|
errcout <- v
|
||||||
|
}
|
||||||
|
waitgroup.Done()
|
||||||
|
}(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
waitgroup.Wait()
|
||||||
|
close(out)
|
||||||
|
close(errcout)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return out, errcout, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user