So let's see what really happens in your source. You have two goroutines (there are more than two, but we are going to focus on explicit ones), mainand readFromChannel.
Let's see what it does readFromChannel:
if channel `c` is not empty before `ti` has expired, print its contents and return, after signalling its completion to wait group.
if `ti` has expired before `c` is not empty, print "TIMED OUT" and return, after signalling its completion to wait group.
now Main:
adds to waitgroup
make a channel `c`
start a goroutine `readFromChannel`
sleep for 5 seconds
send 10 to channel `c`
call wait for waitgroup
Now you can go through the execution thread for your code at the same time (your code may / may not be executed in this order every time, remember this)
1) wg.Add(1)
2) c := make(chan int)
3) go readFromChannel(c, time.After(time.Duration(2)*time.Second))
#timer ti starts#
4) time.Sleep(time.Duration(5) * time.Second)
#MAIN Goroutine begins sleep
#timer ti expires#
5) case <-ti:
6) fmt.Println("TIMED OUT")
7) wg.Done()
# readFromChannel Goroutine returns #
#MAIN Goroutine exits sleep#
8) c<-10
9) ......#DEADLOCK#
, . , - , , . , c <- 10 , - c, goroutine, , 2 . , c , main - goroutine, Deadlock.
? , receive send. , "" .
:
func main() {
wg.Add(1)
c := make(chan int)
go readFromChannel(c, time.After(time.Duration(2)*time.Second))
time.Sleep(time.Duration(5) * time.Second)
c <- 10
wg.Wait()
}
func readFromChannel(c chan int, ti <-chan time.Time) {
loop:
for {
select {
case x := <-c:
fmt.Println("Read", x)
break loop
case <-ti:
fmt.Println("TIMED OUT")
}
}
wg.Done()
}
** .