Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use 'time.After' and 'default' in Golang?

Tags:

go

goroutine

I'm trying to understand a simple code of Golang routines:

package main

import (
    "fmt"
    "time"
)

func sleep(seconds int, endSignal chan<- bool) {
    time.Sleep(time.Duration(seconds) * time.Second)
    endSignal <- true
}

func main() {
    endSignal := make(chan bool, 1)
    go sleep(3, endSignal)
    var end bool

    for !end {
        select {
        case end = <-endSignal:
            fmt.Println("The end!")
        case <-time.After(5 * time.Second):
            fmt.Println("There's no more time to this. Exiting!")
            end = true
        }
    }

}

That's fine, but Why I cannot use a simple default in this "select" block? Something like this:

for !end {
    select {
    case end = <-endSignal:
        fmt.Println("The end.")
    case <-time.After(4 * time.Second):
        fmt.Println("There's no more time to this. Exiting!")
        end = true
    default:
        fmt.Println("No end signal received.")
    }
}

It gets this output:

❯ go run goroutines-timeout.go
No end signal received!
No end signal received!
No end signal received!
No end signal received!
...
The end!

And I can't understand why.

like image 639
Jonathan Beber Avatar asked Aug 29 '16 17:08

Jonathan Beber


People also ask

How to use time after in Golang?

After() Function in Golang With Examples. In Go language, time packages supplies functionality for determining as well as viewing time. The After() function in Go language is used to wait for the duration of time to pass and after that it delivers the actual time on the returned channel.

How do you add time in Golang?

Add() function in Go language is used to add the stated time and duration. Moreover, this function is defined under the time package. Here, you need to import the “time” package in order to use these functions. Here, “t” is the stated time and “d” is the duration that is to be added to the time stated.

What is time second in Golang?

Return Value: It returns the second offset within the minute as provided by “t”. Example 1: // Golang program to illustrate the usage of. // Time.Second() function. // Including main package.

What is a channel in Golang?

So, what are the channels in Golang exactly? Channels are the medium through which goroutines can communicate with each other. In simple terms, a channel is a pipe that allows a goroutine to either put or read the data.


1 Answers

Each time you execute time.After(4 * time.Second) you create a new timer channel. There's no way the select statement can remember the channel it selected on in the previous iteration. You've also taken what was an asynchronous operation and turned it into a busy loop, defeating the purpose of the select statement.

All you need is a a simple select around the two channels you're interested in. It doesn't need to loop at all.

select {
case <-endSignal:
    fmt.Println("The end!")
case <-time.After(4 * time.Second):
    fmt.Println("There's no more time to this. Exiting!")
}

https://play.golang.org/p/jb4EE8e6cw

If you really want to poll multiple times, make the timer outside of the for loop, so that the same one is checked each iteration

timeout := time.After(5 * time.Second)
pollInt := time.Second

for {
    select {
    case <-endSignal:
        fmt.Println("The end!")
        return
    case <-timeout:
        fmt.Println("There's no more time to this. Exiting!")
        return
    default:
        fmt.Println("still waiting")
    }
    time.Sleep(pollInt)
}
like image 196
JimB Avatar answered Nov 05 '22 19:11

JimB