Why is there a dead end

I am trying to understand how the golang channel works. I read a book about go language and found the following example.

package main import ( "fmt" ) // Send the sequence 2, 3, 4, ... to returned channel func generate() chan int { ch := make(chan int) go func() { for i := 2; i <= 100 ; i++ { ch <- i } }() return ch } // Filter out input values divisible by 'prime', send rest to returned channel func filter(in chan int, prime int) chan int { out := make(chan int) go func() { for { if i := <-in; i%prime != 0 { out <- i } } }() return out } func sieve() chan int { out := make(chan int) go func() { ch := generate() for { prime := <-ch ch = filter(ch, prime) out <- prime } }() return out } func main() { primes := sieve() for { fmt.Println(<-primes) } } 

When I run this program, I have a dead end, but when I change the generation function to

 // Send the sequence 2, 3, 4, ... to returned channel func generate() chan int { ch := make(chan int) go func() { for i := 2; ; i++ { ch <- i } }() return ch } 

Then the program will start an infinite loop, but not a dead end. Why do I get a dead end when I delete a condition in a for loop?

+6
source share
2 answers

What do you mean with the principle of blocking?

You can see it on the blog β€œThe nature of channels on the way ”

for unbuffered channel:

http://3.bp.blogspot.com/-vnJIWvlbP-E/UwDVICJKB9I/AAAAAAAANX0/T04V_58i8Vs/s1600/Screen+Shot+2014-02-16+at+10.10.54+AM.png

(Illustration from a blog post, β€œThe Nature of Canals on the Road, ” written by William Kennedy , February 2014.

Unbuffered channels do not have a capacity, therefore they require that both gotoutines are ready to make any exchange .
When a goroutine tries to write a resource to an unbuffered channel, and there is no goryutina waiting to receive the resource, the channel will block the goroutine and make it wait.
When a goroutine tries to read from an unbuffered channel, and there is no fuel waiting to send a resource, the channel will block the goroutine and make it wait .

This is what happens in your case with your reader:

 func main() { primes := sieve() for { fmt.Println(<-primes) } } 

since primes never closes, main remains locked.
It ( main ) is in step 3:

in step 3, the goroutin on the right places a hand in the channel or reads.
This goroutine is also blocked in the channel until the exchange is complete .

The sender never calls close(primes) .

+9
source

Consider a simpler example:

 func generate() chan int { ch := make(chan int) go func() { for i := 2; /*i < 100*/; i++ { ch <- i } }() return ch } func main() { for i := range generate() { fmt.Println(i) } } 

If condition i < 100 uncommented, the goroutine generated by generate stops after sending 98 numbers. However, it does not close the channel, so main does not know that no numbers will be sent anymore, and it simply blocks the channel. Since main now the only goroutine still existing (the other is back), and it blocks, you have a dead end.

+5
source

Source: https://habr.com/ru/post/972689/


All Articles