I'm trying to make my own custom "Channel Timeout". More precisely, the time.After
function inside it. In other words, I'm trying to implement this:
select {
case v := <-c:
fmt.Println("Value v: ", v)
case <-time.After(1 * time.Second):
fmt.Println("Timeout")
}
But unfortunately I ran into a problem.
My implementation is:
func waitFun(wait int) chan int {
time.Sleep(time.Duration(wait) * time.Second)
c := make(chan int)
c <- wait
return c
}
func main() {
c := make(chan int)
go func() {
time.Sleep(3 * time.Second)
c <- 10
}()
select {
case v := <-c:
fmt.Println("Value v: ", v)
case <-waitFun(1):
fmt.Println("Timeout")
}
time.Sleep(4 * time.Second)
}
For some reason this doesn't work. The error is: all goroutines are asleep - deadlock!
. I understand that at some point all goroutines (main and the one introduced with an anonymous function) will go to sleep, but is this the reason for the error or something else? I mean, it's not "infinite sleep" or "infinite wait for something", so it's not a dead lock, right? Additionally, using time.After
also sleeps goroutines, right? What do I need to change to make my program work correctly?
CodePudding user response:
select
statement will evaluate all cases when it is run, so this code will actually wait for the waitFun
to return before it starts listening to any channels. You have to change the waitFun
to return the channel immediately:
func waitFun(wait int) chan int {
c := make(chan int)
go func() {
time.Sleep(time.Duration(wait) * time.Second)
c <- wait
}()
return c
}