Home > Software design >  Why is my custom "Timeout waiting on channel" not working and how to make it work?
Why is my custom "Timeout waiting on channel" not working and how to make it work?

Time:12-28

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
}
  •  Tags:  
  • go
  • Related