From ea1528c789f2cf805dce208958ea9d09f1c65163 Mon Sep 17 00:00:00 2001 From: sgf Date: Wed, 1 Jun 2022 17:29:35 +0300 Subject: [PATCH] new(go): More code from "Go Concurrency Patterns" video. --- go-concurrency-patterns/conc1.go | 85 +++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/go-concurrency-patterns/conc1.go b/go-concurrency-patterns/conc1.go index 82f4a73..80373ba 100644 --- a/go-concurrency-patterns/conc1.go +++ b/go-concurrency-patterns/conc1.go @@ -27,6 +27,7 @@ func main1() { fmt.Println("You're boring. I'm leaving.") } + func main2() { joe := boring("Joe") ann := boring("Ann") @@ -37,6 +38,7 @@ func main2() { fmt.Println("You're both boring. I'm leaving.") } + func fanIn(input1, input2 <- chan string) <-chan string { c := make(chan string) go func() { for { c <- <-input1 } }() @@ -44,6 +46,19 @@ func fanIn(input1, input2 <- chan string) <-chan string { return c } +func fanIns(input1, input2 <- chan string) <-chan string { + c := make(chan string) + go func() { + for { + select { + case s := <- input1: c <- s + case s := <- input2: c <- s + } + } + }() + return c +} + func main3() { c := fanIn(boring("Joe"), boring("Ann")) for i := 0; i < 10; i++ { @@ -52,8 +67,76 @@ func main3() { fmt.Println("You're boring. I'm leaving.") } + +type Message struct { + str string + wait chan bool +} + +func boring4(msg string) <- chan Message { + c := make(chan Message) + // Buffering removes a block in main4() loop, when 'true' is send to + // 'wait' channel. Thus, next message will first arrive from the guy, who + // slept less. Without buffering, main4() will wait until slower guy + // awakes from 'Sleep' and read 'wait' channel, so the Ann will almost + // always be the first one. + waitForIt := make(chan bool, 2) + go func() { + for i := 0; ; i++ { + r := rand.Intn(1e3) + c <- Message{ fmt.Sprintf("%s %d (%d)", msg, i, r), waitForIt } + time.Sleep(time.Duration(r) * time.Millisecond) + <-waitForIt + } + }() + return c +} + +func fanIn4(input1, input2 <- chan Message) <-chan Message { + c := make(chan Message) + go func() { for { c <- <-input1 } }() + go func() { for { c <- <-input2 } }() + return c +} + +func fanIn4s(input1, input2 <- chan Message) <-chan Message { + c := make(chan Message) + go func() { + for { + select { + case s := <- input1: c <- s + case s := <- input2: c <- s + } + } + }() + return c +} + +func main4() { + c := fanIn4s(boring4("Joe"), boring4("Ann")) + for i := 0; i < 5; i++ { + msg1 := <-c; fmt.Println(msg1.str) + msg2 := <-c; fmt.Println(msg2.str) + msg1.wait <- true + msg2.wait <- true + } + fmt.Println("You're boring. I'm leaving.") +} + +// This is the same as main3(). 'wait' channel has no sense here, because +// after reading a message, i immediatelly send "go on" over 'wait' channel to +// the guy, who have spoken right now. +func main41() { + c := fanIn4s(boring4("Joe"), boring4("Ann")) + for i := 0; i < 10; i++ { + msg := <-c; fmt.Println(msg.str) + msg.wait <- true + } + fmt.Println("You're boring. I'm leaving.") +} + func main() { rand.Seed(time.Now().Unix()) - main3() + main4() } -- 2.20.1