package argvpb import ( "fmt" "time" ) // RunIfTakesLonger schedules a function `f` to run after a duration `d`. // It returns a "cancel" function. If the cancel function is called before // the duration `d` has passed, the scheduled function `f` will not be executed. // // This is designed to be used with defer, like so: // // func myFunc() { // cancel := RunIfTakesLonger(time.Second, func() { // fmt.Println("myFunc took more than a second!") // }) // defer cancel() // // // ... rest of the function // } func RunIfTakesLonger(d time.Duration, f func()) (cancel func()) { // time.AfterFunc executes a function in its own goroutine after the // specified duration. It returns a Timer that can be used to cancel it. timer := time.AfterFunc(d, f) // We return a function that stops the timer. // The caller is expected to call this function using `defer`. return func() { // The Stop method returns true if it successfully prevented the // timer from firing. We don't need the return value here, but it's // useful for understanding. timer.Stop() } } // A task that takes less time than the timeout. func shortTask() { fmt.Println("--- Running shortTask (will take 500ms) ---") cancel := RunIfTakesLonger(time.Second, func() { fmt.Println("!!! This should NOT be printed !!!") }) defer cancel() fmt.Println("shortTask: working...") time.Sleep(500 * time.Millisecond) fmt.Println("shortTask: finished.") } // A task that takes more time than the timeout. func longTask() { fmt.Println("\n--- Running longTask (will take 2 seconds) ---") cancel := RunIfTakesLonger(time.Second, func() { fmt.Println(">>> longTask took more than 1 second! Clean-up function executed. <<<") }) defer cancel() fmt.Println("longTask: working...") time.Sleep(2 * time.Second) fmt.Println("longTask: finished.") } func main() { shortTask() longTask() }