Occured incomprehensible deadlock

package main

import (
“fmt”
“time”
)

func main() {
ch := make(chan int, 10)

i := 100

go func() {
	ch <- i
	i++
	time.Sleep(time.Second * 2)
}()

for i := range ch {
	println(i)
}

fmt.Println("end...")

}

fatal error: all goroutines are asleep - deadlock!

I can’t understand why this code is failed.
I think that deadlock is never.

1 Like

Welcome to Golang Bridge! :rocket::fireworks:


1. Forgotten to close the channel

If you’re using channel looping (for i := range ch), you need to close the channel once you’re done with it from the sender side. In your subroutine, you passed the value into the channel and sleep. So, a proper correction should be:

        ...
        go func() {
                ch <- i
                i++
                time.Sleep(time.Second * 2)
                close(ch)
        }
        ...

EDIT:

Reason: main waits forever

the main is continuously waiting for channel to be closed in order to proceed with the range safely. However, instead of getting close signal, the goroutine ended instead, making the for loop wait forever (deadlock waiting). That’s why you’re getting the deadlock.

2. Site Note: Bad Code

in your for loop, println(i) is an unknown function. Should it be fmt.Println(i)?


Cross check

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan int, 10)
	i := 100

	go func() {
		ch <- i
		i++
		time.Sleep(time.Second * 2)
		close(ch)
	}()

	for i := range ch {
		fmt.Println(i)
	}

	fmt.Println("[ END ]")
}
// Output:
// 100
// [ END ]
2 Likes

Thanks for replying :slight_smile:

fmt.Println is right, not println.

I want to repeatdly send some values(100,101,102 … N) but, your code will be done after sending only one time. How can I construct receiver(range loop) and sender(go-routine)?

That, you can start with concurrency planning with crisp and clear data transfers. You can use flow chart or pseudo-code. Here’s one example using pseudo-code:

Process 0 (main):

  1. make channel with 10 buffer space
  2. set my i limit to 100.
  3. start p1 process.
  4. start reading from channel until it closed.
  5. terminate entire program.

Process 1 (let’s name it p1):

  1. loop from 0 to limit, named value
  2. for each value, send value to channel then sleep for 2 seconds
  3. close channel once done.
  4. terminate p1 process.

Keywords:

  1. must be clear with ***WHO does WHAT at WHEN***, every single step for every processes.

You can try it out on your own. I re-coded the example to match the pseudo-code so be self-disciplined over there, all right?

An example answer:

package main

import (
	"fmt"
	"time"
)

func p1(limit int, ch chan int) {
	for value := 0; value < limit; value++ {
		ch <- value
		time.Sleep(time.Second * 2)
	}

	// done with operation, close channel.
	close(ch)
}

func main() {
	ch := make(chan int, 10)
	i := 100

	// start p1 process
	go p1(i, ch)

	// read from channel
	for i := range ch {
		fmt.Println(i)
	}

	fmt.Println("[ END ]")
}
2 Likes

Oh ! Thanks for kind replaying :slight_smile:

I totally understood. Thank you!

Welcome. Feel free to “mark as solved” to close the ticket.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.