Reputation: 6102
I try to implement Timeout pattern for my project. Here is an example code of above link:
c1 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
c1 <- "result 1"
}()
select {
case res := <-c1:
fmt.Println(res)
case <-time.After(1 * time.Second):
fmt.Println("timeout 1")
}
Another example is:
c2 := make(chan string, 1)
go func() {
time.Sleep(2 * time.Second)
c2 <- "result 2"
}()
select {
case res := <-c2:
fmt.Println(res)
case <-time.After(3 * time.Second):
fmt.Println("timeout 2")
}
I can run this example successfully. Then I try apply this to my project. Here is my project code:
for {
select {
case ev := <-c.EventChannel():
// do something here
case <-time.After(2 * time.Second):
// this condition never happend
return
default:
// do nothing as non-blocking channel pattern
}
}
But I don't know why code never run into timeout case. When I move time.After(2 * time.Second)
into separate statement, it works. Here is modified code:
timeout := time.After(2 * time.Second)
for {
select {
case ev := <-c.EventChannel():
// do something here
case <-timeout:
require.Equal(t, "time out after 2s", "")
default:
// do nothing as non-blocking channel pattern
}
}
I don't know the differences between 2 cases. And why first example works. Please help me figure out.
Thanks
Upvotes: 0
Views: 1487
Reputation: 1216
Basically the select statement wont wait if there is a default case, so in your case it just checks for EventChannel
and goes to default case because it is not blocking and it wont wait for 2 seconds timeout
. In every iteration there is a 2 secs
timeout , so it never get executed.
In the second case as the timer is outside the loop it wont reinitialize in each iteration so after 2 seconds
select statement will catch that signal and executes timeout.
If you want to wait for 2 secs
in each iteration then you can do something like this
for {
select {
case ev := <-c.EventChannel():
// do something here
default:
// do nothing as non-blocking channel pattern
}
time.Sleep(2 *time.Second)
}
Upvotes: 3