Consider the toy example below. The code works perfectly but when you interchange the 2 lines marked as replace
, there will be a deadlock. Is there a better way to deal with such a situation when you have different number of sends and receives?
package main
import "fmt"
import "strconv"
func main() {
a := make(chan string)
b := make(chan string)
go func() {
for i := 0; i < 2; i++ {
go func(i int) {
fmt.Println(<-a)
b <- strconv.Itoa(i) + "b" // replace
a <- strconv.Itoa(i) + "a" // replace
}(i)
}
}()
a <- "0"
for i := 0; i < 2; i++ {
fmt.Println(<-b)
}
}
EDIT: using a select statement, there's a chance that a
gets picked up by the select and there's still no way to prevent a deadlock because the goroutines can't execute
package main
import "fmt"
import "strconv"
func main() {
a := make(chan string)
b := make(chan string)
c := make(chan bool)
cancel := make(chan bool)
go func() {
for i := 0; i < 2; i++ {
go func(i int) {
fmt.Println(<-a)
b <- strconv.Itoa(i) + "b" // replace
a <- strconv.Itoa(i) + "a" // replace
c <- true
}(i)
}
}()
go func() {
<-c
<-c
cancel <- true
}()
a <- "0"
loop:
for {
select {
case ain := <-a:
fmt.Println("select", ain)
case bin := <-b:
fmt.Println("select", bin)
case <-cancel:
break loop
}
}
}