如何获得时间。请立即勾选

时间:2015-09-21 22:35:32

标签: go timer

我有一个迭代循环,直到作业启动并运行:

ticker := time.NewTicker(time.Second * 2)
defer ticker.Stop()

started := time.Now()
for now := range ticker.C {
    job, err := client.Job(jobID)
    switch err.(type) {
    case DoesNotExistError:
        continue
    case InternalError:
        return err
    }

    if job.State == "running" {
        break
    }

    if now.Sub(started) > time.Minute*2 {
        return fmt.Errorf("timed out waiting for job")
    }
}

在生产中表现出色。唯一的问题是它使我的测试变慢。他们都在完成前至少等待2秒钟。有没有让time.Tick立刻打勾?

6 个答案:

答案 0 :(得分:6)

ticker := time.NewTicker(period)
for ; true; <-ticker.C {
    ...
}

https://github.com/golang/go/issues/17601

答案 1 :(得分:2)

内部Ticker的实际实现非常复杂。但你可以用goroutine包装它:

func NewTicker(delay, repeat time.Duration) *time.Ticker {
    ticker := time.NewTicker(repeat)
    oc := ticker.C
    nc := make(chan time.Time, 1)
    go func() {
        nc <- time.Now()
        for tm := range oc {
            nc <- tm
        }
    }()
    ticker.C = nc
    return ticker
}

答案 2 :(得分:2)

如果您想立即检查作业,请不要使用代码作为for循环中的条件。例如:

ticker := time.NewTicker(time.Second * 2)
defer ticker.Stop()

started := time.Now()
for {
    job, err := client.Job(jobID)
    if err == InternalError {
        return err
    }

    if job.State == "running" {
        break
    }

    now := <-ticker.C
    if now.Sub(started) > 2*time.Minute {
        return fmt.Errorf("timed out waiting for job")
    }
}

如果你仍然需要检查DoesNotExistError,你需要确保在代码之后这样做,这样你就没有忙碌等待。

答案 3 :(得分:1)

不幸的是,seems Go开发人员不会在任何可预见的将来添加此类功能,因此我们必须应对...

有两种使用股票行情的常用方法:

for循环

给出类似这样的内容:

for <- time.Tick(period) {
    ...
}

使用:


for ; true; <- time.Tick(period) {
    ...
}

for-select循环

给出类似这样的内容:

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

loop:
for {
    select {
        case <- time.Tick(period): 
            f()
        case <- interrupt:
            break loop
    }
}

使用:

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

loop:
for {
    f()

    select {
        case <- time.Tick(period): 
            continue
        case <- interrupt:
            break loop
    }
}

答案 4 :(得分:1)

我煮了这样的东西

{{1}}

答案 5 :(得分:0)

我认为这可能是for-select循环的一个有趣的替代方法,特别是在case的内容不是简单函数的情况下:

具有:

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

ticker := time.NewTicker(period)
defer ticker.Stop()

loop:
for {
    select {
        case <- ticker.C: 
            f()
        case <- interrupt:
            break loop
    }
}

使用:

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

ticker := time.NewTicker(period)
defer ticker.Stop()
firstTick := false

// create a wrapper of the ticker that ticks the first time immediately
tickerChan := func() <-chan time.Time {
  if !firstTick {
    firstTick = true
    c := make(chan time.Time, 1)
    c <- time.Now()
    return c
  }

  return ticker.C
}

loop:
for {
    select {
        case <- tickerChan(): 
            f()
        case <- interrupt:
            break loop
    }
}