Reputation: 13825
Why doesn't this Golang code to select among multiple time.After channels work?
See code below. The 'timeout' message is never issued. Why?
package main
import (
"fmt"
"time"
)
func main() {
count := 0
for {
select {
case <-time.After(1 * time.Second):
count++
fmt.Printf("tick %d\n", count)
if count >= 5 {
fmt.Printf("ugh\n")
return
}
case <-time.After(3 * time.Second):
fmt.Printf("timeout\n")
return
}
}
}
Run it on Playground: http://play.golang.org/p/1gku-CWVAh
Output:
tick 1
tick 2
tick 3
tick 4
tick 5
ugh
Upvotes: 12
Views: 3774
Reputation: 11551
Even @Ainar-G has already provided the answer, another possibility is to use time.Tick(1e9)
to generate a time tick on every second and then listen for timeAfter
channel after the specified period.
package main
import (
"fmt"
"time"
)
func main() {
count := 0
timeTick := time.Tick(1 * time.Second)
timeAfter := time.After(5 * time.Second)
for {
select {
case <-timeTick:
count++
fmt.Printf("tick %d\n", count)
if count >= 5 {
fmt.Printf("ugh\n")
return
}
case <-timeAfter:
fmt.Printf("timeout\n")
return
}
}
}
Upvotes: 5
Reputation: 36189
Because time.After
is a function, so on every iteration it returns a new channel. If you want this channel to be the same for all iterations, you should save it before the loop:
timeout := time.After(3 * time.Second)
for {
select {
//...
case <-timeout:
fmt.Printf("timeout\n")
return
}
}
Playground: http://play.golang.org/p/muWLgTxpNf.
Upvotes: 19