-2

I know we can read from buffered close channels. So, I feel very confident that we can do from unbuffered as well. However, I am not able to test it out.

func test(c chan int) {
    time.Sleep(10 * time.Millisecond)
    close(c)
    fmt.Println(<-c)
}

func main() {
    c := make(chan int)
    go test(c)
    c <- 5
}

Output

panic: send on closed channel

goroutine 1 [running]:
main.main()
        /Users/tanmay.jhazomato.com/Projects/search-service/practice.go:17 +0x85

Process finished with the exit code 2

As far as I know, in this code. First c<-5 should be executed before channel getting closed by test go routine. However, that's not the case. Can somebody tell me when cooperative scheduling is not working here? Why is it that the test go routine is executing first?

Tanmay Jha
  • 11
  • 5
  • You're not trying to *read from* the closed channel. You are trying to *write to* the closed channel. You've started by setting up a race, where if the goroutine running `test` closes the channel *before* `main` tries to write, the program crashes. (And then you cleverly guarantee that `test` wins the race, so that the program *always* crashes.) – torek Apr 01 '22 at 21:50

1 Answers1

1

A send to an unbuffered channel will block until another goroutine reads from it. So, while the main goroutine is waiting to write to the channel, the second goroutine closes it, and the program fails with a send on the closed channel.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • But before blocking, data would have already been written to the channel right? Because then only it would be possible for any other go routine to read from it. – Tanmay Jha Apr 01 '22 at 21:25
  • @TanmayJha: No, `main` blocks waiting for someone to try a receive, and then unblocks once the receive happens or the channel is closed (whichever occurs first). Then `main` tries to send, and the condition that unblocked `main` was the channel getting closed. – torek Apr 01 '22 at 21:57
  • A write to an unbuffered channel happens only when another goroutine is ready to read from it. An unbuffered channel is a synchronization mechanism, not a data storage mechanism – Burak Serdar Apr 01 '22 at 21:59
  • Can anyone explain the flow of control if no close(channel) was present. Basically, control reaches the point where it tries to write data in channel. This is a blocking operation. So, it goes to the other go routine where it finds a channel reader. Now what happens? Do we switch again to main where data was being written to channel and again switch back to the other go routine where it is being consumed? – Tanmay Jha Apr 01 '22 at 22:02