Reputation: 867
Consider the following go playground
package main
import "fmt"
func main() {
var chan_array [2]chan int
chan1 := make(chan int)
chan2 := make(chan int)
chan_array[0] = chan1
chan_array[1] = chan2
for i := 0; i < 2; i++ {
go func() {
select {
case x := <- chan_array[i]:
if (x == 0) {
return
}
fmt.Println(x)
}
}()
}
chan1<- 1
chan2<- 2
chan1<- 0
chan2<- 0
}
The code above is trying to create 2 running goroutines with that listens to the channel to signal print or close.
But the above code run into dead lock.
I am not exactly sure why
Can someone point out my mistake?
Thanks
Upvotes: 2
Views: 291
Reputation: 54325
By the time the goroutines are running the variable i
has already incremented. Pass it as a function parameter instead.
In fact, never rely on variables from a function closure in goroutines. It's too unreliable.
Upvotes: 1
Reputation:
There are some problems:
What is the value of i
when chan_array[i-1]
runs:
for i := 0; i < 2; i++ {
go func() {
select {
case x := <- chan_array[i-1]:
if x == 0 {
return
}
fmt.Println(x)
}
}()
}
try this:
for i := 0; i < 2; i++ {
go func(i int) {
select {
case x := <-chan_array[i]:
if x == 0 {
return
}
fmt.Println(x)
}
}(i)
}
Let's simplify your code (with some corrections):
package main
import "fmt"
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go routine(chan1)
go routine(chan2)
chan1 <- 1
chan2 <- 2
chan1 <- 0
chan2 <- 0
}
func routine(ch chan int) {
select {
case x := <-ch:
if x == 0 {
return
}
fmt.Println(x)
}
}
With these:
chan1 <- 1
chan2 <- 2
fatal error:
all goroutines are asleep - deadlock!
your goroutines finished and no goroutines listening to chan1
and chan1
here:
chan1 <- 0
chan2 <- 0
Your corrected working sample code is:
package main
import "fmt"
func main() {
chan1 := make(chan int)
chan2 := make(chan int)
go routine(chan1)
go routine(chan2)
chan1 <- 1
chan2 <- 2
chan1 <- 0
chan2 <- 0
}
func routine(ch chan int) {
for {
select {
case x := <-ch:
if x == 0 {
return
}
fmt.Println(x)
}
}
}
output:
1
2
Upvotes: 4