28

I am currently studying, and I miss setTimeout from Nodejs in golang. I haven't read much yet, and I'm wondering if I could implement the same in go like an interval or a loopback.

Is there a way that I can write this from node to golang? I heard golang handles concurrency very well, and this might be some goroutines or else?

//Nodejs
function main() {

 //Do something

 setTimeout(main, 3000)
 console.log('Server is listening to 1337')
}

Thank you in advance!

//Go version

func main() {
  for t := range time.Tick(3*time.Second) {
    fmt.Printf("working %s \n", t)
  }

  //basically this will not execute..
  fmt.Printf("will be called 1st")
}
peterh
  • 11,875
  • 18
  • 85
  • 108
Hokutosei
  • 2,114
  • 5
  • 24
  • 42

4 Answers4

43

The closest equivalent is the time.AfterFunc function:

import "time"

...
time.AfterFunc(3*time.Second, somefunction)

This will spawn a new goroutine and run the given function after the specified amount of time. There are other related functions in the package that may be of use:

  • time.After: this version will return a channel that will send a value after the given amount of time. This can be useful in combination with the select statement if you want a timeout while waiting on one or more channels.

  • time.Sleep: this version will simply block until the timer expires. In Go it is more common to write synchronous code and rely on the scheduler to switch to other goroutines, so sometimes simply blocking is the best solution.

There is also the time.Timer and time.Ticker types that can be used for less trivial cases where you may need to cancel the timer.

James Henstridge
  • 42,244
  • 6
  • 132
  • 114
  • 1
    thanks james. I'm working out your example. and I cant seem to get it right. my program quits and does not loop. I need to make a continues loop and non-blocking. like I am serving a web page with network stats while looping through a list of servers on background for stats. I guess i need to read more. – Hokutosei Jun 06 '14 at 07:07
  • 1
    Your program will exit with the `main` function completes, so that might be what is going wrong. If you want the program to periodically do some work, just use a `for { ... }` loop with a `time.Sleep` call at the end, or alternatively `for t := range time.Tick(3*time.Second) { ... }`. – James Henstridge Jun 06 '14 at 07:11
  • I got it. but of course this wont be what i wanted to do. anyway, I got the idea though some isn't clear to me yet(like non-blocking stuff), I'm used to what nodejs gaved me. thank you for your help :D I'll read more – Hokutosei Jun 06 '14 at 07:42
  • If you are coming from an async framework like Node.js or Twisted, it's probably best to unlearn most of what you know about IO and write your code as if it is synchronous. While a read from a socket may look like a blocking syscall from the point of view of your goroutine, Go will actually schedule another goroutine on your OS thread, and only wake you up when there is data available. It is rare to deal with APIs that take completion callbacks as an argument. – James Henstridge Jun 06 '14 at 08:14
4

This website provides an interesting example and explanation of timeouts involving channels and the select function.

// _Timeouts_ are important for programs that connect to
// external resources or that otherwise need to bound
// execution time. Implementing timeouts in Go is easy and
// elegant thanks to channels and `select`.

package main

import "time"
import "fmt"

func main() {

    // For our example, suppose we're executing an external
    // call that returns its result on a channel `c1`
    // after 2s.
    c1 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c1 <- "result 1"
    }()

    // Here's the `select` implementing a timeout.
    // `res := <-c1` awaits the result and `<-Time.After`
    // awaits a value to be sent after the timeout of
    // 1s. Since `select` proceeds with the first
    // receive that's ready, we'll take the timeout case
    // if the operation takes more than the allowed 1s.
    select {
    case res := <-c1:
        fmt.Println(res)
    case <-time.After(1 * time.Second):
        fmt.Println("timeout 1")
    }

    // If we allow a longer timeout of 3s, then the receive
    // from `c2` will succeed and we'll print the result.
    c2 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c2 <- "result 2"
    }()
    select {
    case res := <-c2:
        fmt.Println(res)
    case <-time.After(3 * time.Second):
        fmt.Println("timeout 2")
    }
}

You can also run it on the Go Playground

Geige V
  • 1,389
  • 1
  • 16
  • 28
1

another solution could be to implement an

Immediately-Invoked Function Expression (IIFE) function like:

go func() {
  time.Sleep(time.Second * 3)
  // your code here
}()
internet3
  • 41
  • 1
  • 4
  • 1
    This wont most like work as expected with multiple goroutines on a single processor. E.g. if there will be multiple gourutines they will be executed in unknown order and block executiion of other goroutines and sleep will sum up. – user2846569 Aug 01 '18 at 19:10
1

you can do this by using sleep function and give your duration you need

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("First")
    time.Sleep(5 * time.Second)
    fmt.Println("second")
}