I'm having a hard time understanding how buffered channels work. Based on the following example, i'm trying to utilize 2 threads at a time to print out the current time, with approximately 2 second delays between every 2 go calls:
package main
import "fmt"
import "time"
func main() {
returnCurrentTime := func() string {
return time.Now().String()
}
c := make(chan string, 2)
asyncReturnCurrentTime := func(c chan string) {
time.Sleep(2001 * time.Millisecond)
c <- returnCurrentTime()
}
for i := 1; i != 7; i++ {
go asyncReturnCurrentTime(c)
if(i % 3 == 0) {
fmt.Println(<- c)
fmt.Println(<- c)
fmt.Println(<- c)
fmt.Println()
}
}
}
This produces
2013-02-27 03:17:50
2013-02-27 03:17:50
2013-02-27 03:17:50
2013-02-27 03:17:52
2013-02-27 03:17:52
2013-02-27 03:17:52
What i'm expecting regarding the seconds is 2 second delays between ever 2 go calls and in this case the following result
2013-02-27 03:17:50
2013-02-27 03:17:50
2013-02-27 03:17:52 <- 3rd call with 2 buffer slots
2013-02-27 03:17:54
2013-02-27 03:17:54
2013-02-27 03:17:56 <- 3rd call with 2 buffer slots
Obviously i misunderstood the concept of buffered channels, would somebody please be kind enough to explain the fault in my logic and how to achieve the expected result?
Thank you
Effectively, you are running:
package main
import (
"fmt"
"time"
)
func main() {
returnCurrentTime := func() string {
return time.Now().String()
}
c := make(chan string, 2)
asyncReturnCurrentTime := func(c chan string) {
time.Sleep(2001 * time.Millisecond)
c <- returnCurrentTime()
}
go asyncReturnCurrentTime(c)
go asyncReturnCurrentTime(c)
go asyncReturnCurrentTime(c)
fmt.Println(<-c)
fmt.Println(<-c)
fmt.Println(<-c)
fmt.Println()
go asyncReturnCurrentTime(c)
go asyncReturnCurrentTime(c)
go asyncReturnCurrentTime(c)
fmt.Println(<-c)
fmt.Println(<-c)
fmt.Println(<-c)
fmt.Println()
}
Output:
2013-02-26 21:28:22.069581655 -0500 EST
2013-02-26 21:28:22.069688722 -0500 EST
2013-02-26 21:28:22.069695217 -0500 EST
2013-02-26 21:28:24.070985411 -0500 EST
2013-02-26 21:28:24.070999309 -0500 EST
2013-02-26 21:28:24.071002661 -0500 EST
Both the channel and the value expression are evaluated before communication begins. Communication blocks until the send can proceed.
The returnCurrentTime()
expression (the timestamp) is evaluated immediately, before an attempt is made to send. It's not a timestamp for the send. The send may happen later if the buffer is full.
Also, measuring actual send and receive times, the buffering delay for chan c
is going to be inconsequential: send, send, block, receive, unblock, send. For example,
c <-; 2013-02-26 23:29:34.505456624 -0500 EST
c <-; 2013-02-26 23:29:34.505467030 -0500 EST
<- c; 2013-02-26 23:29:34.505468497 -0500 EST
c <-; 2013-02-26 23:29:34.505518015 -0500 EST
c <-; 2013-02-26 23:31:36.506659943 -0500 EST
c <-; 2013-02-26 23:31:36.506664832 -0500 EST
<- c; 2013-02-26 23:31:36.506669302 -0500 EST
c <-; 2013-02-26 23:31:36.506696540 -0500 EST