From 824662270a9cf18558e53c4dda2cb819dff4d686 Mon Sep 17 00:00:00 2001 From: tkms0106 <23391543+tkms0106@users.noreply.github.com> Date: Tue, 15 Sep 2020 19:42:58 +0900 Subject: [PATCH 1/2] Add tee-channel sample 4. Concurrency Patterns in Go ->The tee-channel --- .../the-tee-channel/fig-tee-channel.go | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 concurrency-patterns-in-go/the-tee-channel/fig-tee-channel.go diff --git a/concurrency-patterns-in-go/the-tee-channel/fig-tee-channel.go b/concurrency-patterns-in-go/the-tee-channel/fig-tee-channel.go new file mode 100644 index 0000000..d8f9c68 --- /dev/null +++ b/concurrency-patterns-in-go/the-tee-channel/fig-tee-channel.go @@ -0,0 +1,98 @@ +package main + +import ( + "fmt" +) + +func main() { + repeat := func( + done <-chan interface{}, + values ...interface{}, + ) <-chan interface{} { + valueStream := make(chan interface{}) + go func() { + defer close(valueStream) + for { + for _, v := range values { + select { + case <-done: + return + case valueStream <- v: + } + } + } + }() + return valueStream + } + take := func( + done <-chan interface{}, + valueStream <-chan interface{}, + num int, + ) <-chan interface{} { + takeStream := make(chan interface{}) + go func() { + defer close(takeStream) + for i := 0; i < num; i++ { + select { + case <-done: + return + case takeStream <- <-valueStream: + } + } + }() + return takeStream + } + orDone := func(done, c <-chan interface{}) <-chan interface{} { + valStream := make(chan interface{}) + go func() { + defer close(valStream) + for { + select { + case <-done: + return + case v, ok := <-c: + if ok == false { + return + } + select { + case valStream <- v: + case <-done: + } + } + } + }() + return valStream + } + tee := func( + done <-chan interface{}, + in <-chan interface{}, + ) (_, _ <-chan interface{}) { + out1 := make(chan interface{}) + out2 := make(chan interface{}) + go func() { + defer close(out1) + defer close(out2) + for val := range orDone(done, in) { + var out1, out2 = out1, out2 + for i := 0; i < 2; i++ { + select { + case <-done: + case out1 <- val: + out1 = nil + case out2 <- val: + out2 = nil + } + } + } + }() + return out1, out2 + } + done := make(chan interface{}) + defer close(done) + + out1, out2 := tee(done, take(done, repeat(done, 1, 2), 4)) + + for val1 := range out1 { + fmt.Printf("out1: %v, out2: %v\n", val1, <-out2) + } +} From bb10a902ef1bcaf788d2c3ab9475ceb24f05c5fe Mon Sep 17 00:00:00 2001 From: tkms0106 <23391543+tkms0106@users.noreply.github.com> Date: Tue, 15 Sep 2020 19:59:10 +0900 Subject: [PATCH 2/2] Update name of variables to make it clearer --- .../the-tee-channel/fig-tee-channel.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/concurrency-patterns-in-go/the-tee-channel/fig-tee-channel.go b/concurrency-patterns-in-go/the-tee-channel/fig-tee-channel.go index d8f9c68..c9afd1c 100644 --- a/concurrency-patterns-in-go/the-tee-channel/fig-tee-channel.go +++ b/concurrency-patterns-in-go/the-tee-channel/fig-tee-channel.go @@ -73,14 +73,14 @@ func main() { defer close(out1) defer close(out2) for val := range orDone(done, in) { - var out1, out2 = out1, out2 + var out1copy, out2copy = out1, out2 for i := 0; i < 2; i++ { select { case <-done: - case out1 <- val: - out1 = nil - case out2 <- val: - out2 = nil + case out1copy <- val: + out1copy = nil + case out2copy <- val: + out2copy = nil } } }