R
R
Roman Mirilaczvili2020-06-25 12:37:19
go
Roman Mirilaczvili, 2020-06-25 12:37:19

Why is it deadlocked? Is there something wrong with the recipient?

I understand the work of Go channels. I wrote a test program, the essence of which is the sequential processing of data received in one channel from another.
I get an error

fatal error: all goroutines are asleep - deadlock!

the code
package main

import (
  "fmt"
  "time"
)

var numChan chan int
var labelChan <-chan string

func main() {
  input := []int{3, 1, 8, 7, 5, 9, 2}
  numChan = make(chan int)

  go func() {
    labelsReceiver(labelChan)
  }()
  time.Sleep(time.Millisecond) // Так попытался убедиться, что получатель стартует первым. Не знаю как правильно сделать.

  go func() {
    labelChan = labelsEmitter(numChan)
  }()

  for _, num := range input {
    fmt.Println(num)
    numChan <- num
  }
}

func labelsEmitter(numbers chan int) <-chan string {
  fmt.Println("go labelsEmitter")
  out := make(chan string, 3)
  defer close(out)
  for num := range numbers {
    time.Sleep(time.Millisecond * 200)
    str := fmt.Sprintf("Number %d", num)
    out <- str
  }
  return out
}

func labelsReceiver(labelChanRcv <-chan string) {
  fmt.Println("go labelsReceiver")
  for label := range labelChanRcv {
    fmt.Println(label)
  }
}

But if you increase the size of the buffered channel in line , say, up to 10, then the program, although it does not display the label, does not crash with the error above.
out := make(chan string, 3)

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexey Maslov, 2020-06-25
@2ord

Try like this:

package main

import (
  "fmt"
  "time"
)

var numChan chan int
var outChan chan string

func main() {
  input := []int{3, 1, 8, 7, 5, 9, 2}
  numChan = make(chan int)
  outChan = make(chan string)
  go func() {
    labelsReceiver(outChan)
  }()
  time.Sleep(time.Millisecond) // Так попытался убедиться, что получатель стартует первым. Не знаю как правильно сделать.

  go func() {
    labelsEmitter(numChan, outChan)
  }()

  for _, num := range input {
    fmt.Println(num)
    numChan <- num
  }
  close(numChan)
  close(outChan)
}

func labelsEmitter(numbers chan int, outChan chan string) {
  fmt.Println("go labelsEmitter")
  //out := make(chan string, 3)
  //defer close(out)
  for num := range numbers {
    time.Sleep(time.Millisecond * 200)
    str := fmt.Sprintf("Number %d", num)
    outChan <- str
  }
  return
}

func labelsReceiver(labelChanRcv <-chan string) {
  fmt.Println("go labelsReceiver")
  for label := range labelChanRcv {
    fmt.Println("label", label)
  }
}

I
Ilya Zyabirov, 2020-06-25
@passionkillah

I could be wrong, but I think it's because you're overriding labelChan. First, you pass in the labelsReceiver the variable that was declared above main() (it is passed by value - that is, in labelsReceiver you interact with a copy of the labelChan variable), and then you return another channel from the labelsEmitter method to which you write, but from which don't read. And when the buffer is increased to 10, there is no error because the numbers in the input are less than 10 => they are simply written to the buffer, but still no one reads them.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question