I've created a Go playground sample that illustrates what I'm talking about.
In the example, I create one goroutine, func2, which I would simply like to wait for inputs through its channel and print the value once it arrives.
func func2(ch chan int) {
fmt.Println("func2")
v:=<-ch
fmt.Println(v)
}
Then, in a loop, I create goroutines for another function, and these are part of a WaitGroup.
func func1(ch chan int, wg *sync.WaitGroup) {
fmt.Println("func1")
ch <- 11032
wg.Done()
}
And in main, I wait for the WaitGroup. I'm running into a deadlock and I'm not sure how to fix it. Just so it's clear what I'm trying to achieve, I want func2 to stay open as a thread once I call it, to process n values, where n is the number of goroutines I call for func1. I considered using a WaitGroup Wait inside of func2, but I don't want it blocking, as it needs to process new data from func1 as it's sent.
I think you're getting a deadlock because your func2
is consuming only 1 value from ch
and then finishing. Then the other func1
goroutines are stuck waiting for ch
to be available to write into, which they cannot do because there is no other goroutine to read from ch
on the other end.
Since you want func2
to continually consume values from ch
until ch
is closed, you need to create a loop in func2
like so:
func func2(ch chan int) {
fmt.Println("func2")
for v := range ch {
fmt.Println(v)
}
}
This will keep func2
"alive" and reading from ch
until you do close(ch)
somewhere else. The appropriate place to close ch
in your example would likely be in main
after wg.Wait()
.
If you want to be sure to see the results from all Println
statements before the program finishes, you should also use some synchronization mechanism to wait for func2
to finish. Otherwise main
will end immediately after close(ch)
which may or may not be before func2
has printed every value it received.
A common technique for this is a "done" channel. For example:
func func2(ch chan int, done chan bool) {
fmt.Println("func2")
for v := range ch {
fmt.Println(v)
}
done <- true
}
and in main
:
done := make(chan bool)
go func2(ch, done)
...
wg.Wait()
close(ch)
<-done
Using chan struct{}
(empty struct) is also very common since empty struct requires no memory.