循环倒计时器

时间:2016-03-17 12:58:09

标签: algorithm go timer

我目前有这个代码试图计算触发某个条件所用的时间。 (伪):

timeDelay = 900000 // time.Microsecond
for {
   // if a certain something happens, start a counting (time)
   if (certainSomething) {
      startTime = time.Now();

      if !prevTime.IsZero() {
        // add the time elapsed time to timeTick
        diffTime = time.Since(prevTime)
        timeTick = timeTick + diffTime
      }

      prevTime = startTime
   }

   if (timeTick < timeDelay) { // lessThan()
      // still has not reached target count (time elapsed)
      fmt.Println("Not Yet")
      // we dont want to get to the end of the loop yet
      continue
   }

   if (timeTick > timeDelay) { // greaterThan()
      // has finally reached the target count (time elapsed)
      fmt.Println("Yes! Finally")
      // yes the delay has been reached lets reset the time
      // and if `thisHappened` is triggered again, lets start counting again
      timeTick = time.Duration(0 * time.Microsecond)
   }

   // function shouldn't be called if the elapsed amount
   //      of time required has not yet been reached
   iShouldOnlyBeCalledWhenDelayHasBeenReached();
}

我也将它们用作辅助函数(实际代码)

func lessThan(diff time.Duration, upper int) bool {
    return diff < time.Duration(upper)*time.Microsecond && diff != 0
}

func greaterThan(diff time.Duration, upper int) bool {
    return diff > time.Duration(upper)*time.Microsecond
}

但是,我对自己的表现并不满意。我不应该算数,对吗?我应该倒计时......我只是感到困惑,需要帮助我应该采用什么方法。

我想要发生什么:
1.当timeDelay发生时,certainSomething到0的倒计时开始 2.在倒计时到达0之前,请勿致电iShouldOnlyBeCalledWhenDelayHasBeenReached 这应该都发生在一个循环中,一个服务器循环准确地接收数据包。

我的问题:
1.我应该怎么做以实现倒计时风格?

谢谢,任何建议或示例代码都会有很大帮助。

  

注意:循环中还有其他功能。做其他事情。这是主循环。我无法做到Sleep

4 个答案:

答案 0 :(得分:2)

您可以设置频道,以便在您超出时间时通知您。

以下是on play

的示例

它有一个额外的好处,在select语句中,您可以将其他通道用于其他目的。例如,如果你在这个循环中做其他工作,你也可以在goroutine中产生那个工作并让它将结果发送回另一个通道。
然后在timeDelay之后或其他工作完成时退出,或者其他任何内容。

package main

import (
    "fmt"
    "time"
)

func main() {
    certainSomething := true // will cause time loop to repeat

    timeDelay := 900 * time.Millisecond // == 900000 * time.Microsecond

    var endTime <-chan time.Time // signal for when timer us up

    for {
        // if a certain something happens, start a timer
        if certainSomething && endTime == nil {
            endTime = time.After(timeDelay)
        }
        select {
        case <-endTime:
            fmt.Println("Yes Finally!")
            endTime = nil
        default:
            fmt.Println("not yet")
            time.Sleep(50 * time.Millisecond) // simulate work
            continue
        }

        // function shouldn't be called if the elapsed amount
        //      of time required has not yet been reached
        iShouldOnlyBeCalledWhenDelayHasBeenReached() // this could also just be moved to the <- endtime block above
    }
}

func iShouldOnlyBeCalledWhenDelayHasBeenReached() {
    fmt.Println("I've been called")
}

答案 1 :(得分:2)

因为这是一个你说的游戏,所以你听起来像是:

  • 想做X量的工作
  • 如果工作时间超过delay金额,请停止工作并重新循环

如果是这种情况,那么您有一些选项和模式。

想到了{p> time.After

我喜欢select语句中time.After的清洁度。没有渠道或goroutines需要处理它。

此模式还具有使用goroutine作为主游戏逻辑的额外好处。

在游戏中:http://play.golang.org/p/FIiUJ0CHZz

更改time.After()以查看其实际效果。

func main() {

    for {

        // creating a new channel on each loop will allow the
        // GC to collect any game stuff that completes after the timeout.
        done := make(chan int)

        // main game func, doing your other stuff.
        // since this is in a goroutine, it won't block
        // and we can check the state in the select.
        go func(){

            // complicated logic here!
            //

            // you must issue an "I am done!"
            done <- 1
        }()

        // this will block the for loop until a timeout occurs
        select {
            case <- done:
                continue
            case <- time.After(1000 * time.Nanosecond):
                iShouldOnlyBeCalledWhenDelayHasBeenReached()
        }
    }
}

答案 2 :(得分:1)

如果您无法进行常规睡眠,则应使用time.Time.Addtime.Time.After(或time.Time.Before)功能。

沿着这些线路的东西

package main         

import "time"        

func main() {        

    var d = 1000 * time.Microsecond
    var t = time.Now().Add(d)

    for {            
        if time.Now().Before(t) {
            continue 
        }            

        do_something()
    }                
}

或者在您可以睡觉的例行程序中将您必须在一段时间后运行的方法逐出:

package main         

import "time"        

func main() {

    var d = 1000 * time.Microsecond

    go func() {
        time.Sleep(d)
        do_something()
    }()
}

答案 3 :(得分:0)

我认为这可以解决您的问题。

package main

import (
    "fmt"
    "time"
)

func main() {
    time.Sleep(2 * time.Second)
    fmt.Println("Time is up!")
}

Playground