-2

As mentioned here: Buffered channel of size 1 can give you one delayed send of guarantee

In the below code:

package main

import (
    "fmt"
    "time"
)

func display(ch chan int) {
    time.Sleep(5 * time.Second)
    fmt.Println(<-ch) // Receiving data
}

func main() {
    ch := make(chan int, 1) // Buffered channel - Send happens before receive
    go display(ch)
    fmt.Printf("Current Unix Time: %v\n", time.Now().Unix())
    ch <- 1 // Sending data
    fmt.Printf("Data sent at: %v\n", time.Now().Unix())
}

Output:

Current Unix Time: 1610599724
Data sent at: 1610599724

Does buffered channel of size 1, guarantee the receiving of data, if not displaying the data in the above code?

How to verify, if display() received data?

overexchange
  • 15,768
  • 30
  • 152
  • 347

1 Answers1

2

The only way you can guarantee the receiving goroutine received data is tell the caller that it did:

func display(ch chan int,done chan struct{}) {
    time.Sleep(5 * time.Second)
    fmt.Println(<-ch) // Receiving data
    close(done)
}

func main() {
    ch := make(chan int, 1) // Buffered channel - Send happens before receive
    done:=make(chan struct{})
    go display(ch,done)
    fmt.Printf("Current Unix Time: %v\n", time.Now().Unix())
    ch <- 1 // Sending data
    fmt.Printf("Data sent at: %v\n", time.Now().Unix())
    <-done
   // received data
}

You can also use a sync.WaitGroup for the same purpose.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • For your point: "only way you can guarantee the receiving goroutine received data". Can't unbuffered channel gurantee receive? as shown here https://play.golang.org/p/LWE_BREje4C – overexchange Jan 14 '21 at 05:03
  • In an unbuffered channel, write implies read happened. Not so in a buffered channel. – Burak Serdar Jan 14 '21 at 05:09
  • `close(done)` is not a guranteed delivery, because signal send happens before signal receive, for `done`, if you see the timestamps, as shown here: https://play.golang.org/p/0sG0-S5ev9t – overexchange Jan 14 '21 at 05:22
  • `<-done` returning implies `close(done)` is completed. That doesn't imply the timestamps are printed in the order you want. Both goroutines are still working. You cannot tell which goroutine will print the timestamp first. – Burak Serdar Jan 14 '21 at 05:28
  • Just comment (`// <-done`) code works, Isn't it? – overexchange Jan 14 '21 at 05:32
  • I don't understand your question – Burak Serdar Jan 14 '21 at 05:39
  • For your point: "tell the caller that it did" using `close(done)`, am saying that `close(done)` is not a guaranteed delivery. – overexchange Jan 14 '21 at 05:40
  • How so? In this case, it is guaranteed, because of the read from the channel in the main goroutine. – Burak Serdar Jan 14 '21 at 05:52
  • The moment `<-done` returns, you are sure that `close` is called. How is that not guaranteed delivery? – Burak Serdar Jan 14 '21 at 05:58
  • Just verify by this line: `// <-done`. `close(done) // var done chan struct{}` does not block `display()`, where as `done <- 1 // var done chan int` blocks `display()` – overexchange Jan 14 '21 at 06:01
  • Just to be clear: your initial question is about making sure `display` received the data in the buffered channel. When `<-done` returns in main, you can be sure that `display` received that. There is no need for `display` to be blocked. – Burak Serdar Jan 14 '21 at 06:03
  • I understand this point, but let me accept your answer – overexchange Jan 14 '21 at 06:04