Scheduling a Function Call to the Exact start of a Minute

agolangf · · 586 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hello fellow Gophers,</p> <p>I am trying to schedule a function call to the exact start of a Minute every Minute (or at least as close as possible to the 0 Second of the Minute) and I came up with the following Go Program. There are Several things about this Program that I don&#39;t like and I would like to ask what you all think about this.</p> <pre><code>package main import ( &#34;fmt&#34; &#34;time&#34; ) func main() { var currentTime = time.Now() var startTime = currentTime.Truncate(time.Minute).Add(time.Minute) fmt.Printf(&#34;Current: \t%v\nStartAt: \t%v\n&#34;, currentTime, startTime) var duration = startTime.Sub(currentTime) time.Sleep(duration) var ticker = time.NewTicker(1 * time.Minute).C var timeout = time.NewTimer(5 * time.Minute).C loop: for { select { case tick := &lt;-ticker: fmt.Printf(&#34;Tick: \t\t%v\n&#34;, tick) case &lt;-timeout: break loop } } fmt.Printf(&#34;EndTime: \t%v\n&#34;, time.Now()) } </code></pre> <p>Output of the Program:</p> <pre><code>Current: 2016-02-09 00:03:19.45209065 +0100 CET StartAt: 2016-02-09 00:04:00 +0100 CET Tick: 2016-02-09 00:05:00.000363957 +0100 CET Tick: 2016-02-09 00:06:00.000370028 +0100 CET Tick: 2016-02-09 00:07:00.000368027 +0100 CET Tick: 2016-02-09 00:08:00.000387177 +0100 CET Tick: 2016-02-09 00:09:00.00037631 +0100 CET EndTime: 2016-02-09 00:09:00.000421761 +0100 CET </code></pre> <p>One of the things I don&#39;t like is that the time to the First Tick from the start of the Program can be up to 2 Minutes. If the Ticker would release a Tick immediately then it would cut that Time down to only 1 Minute. I could, of course, Repeat the function Call in front of the loop which would also cut down that time to around 1 minute, but I just don&#39;t like to repeat myself in code and would like to avoid it if there is a better way.</p> <p>I also don&#39;t like that I have to rely on time.Sleep(duration) to set the start time of the Ticker and the Timer. Is there a way to start the Ticker explicitly? If that is possible I could then replace the time.Sleep with a time.After and a additional case in the Select which would then Start the Ticker and Timer.</p> <p>What do you think? Is this a good way of doing this? Are there ways to make this code a bit nicer? </p> <p>Thank you in advance. </p> <hr/>**评论:**<br/><br/>motojo: <pre><p>EDIT: Ignore this code, look at the subcomments.</p> <p>Here is what I do in my programs when I want to run on the minute:</p> <pre><code>func minuteTicker() *time.Ticker { // Current time now := time.Now() // Get the number of seconds until the next minute var d time.Duration d = time.Second * time.Duration(60-now.Second()) // Time of the next tick nextTick := now.Add(d) // Subtract next tick from now diff := nextTick.Sub(time.Now()) // Return new ticker return time.NewTicker(diff) } </code></pre></pre>Nooby1990: <pre><p>I am not sure I understand this correctly.</p> <p>Wouldn&#39;t diff just be equal to d since you are adding d to now and then subtract now again? Or at least almost equal since some fractions of a second have passed between the 2 time.Now calls. Couldn&#39;t you just skip the adding and subtracting and get the same result?</p> <p>And since d is basically a random duration only the first Tick would be exactly on the Minute and the following Ticks would be timed for the random duration d. I would then need to start a Ticker for the Minute intervals on the First tick of this ticker. Which is basically what I am doing above with <code>time.Sleep(duration)</code>.</p></pre>motojo: <pre><p>You&#39;re right, some code could be skipped. I shortened it.</p> <p>Here is the code so you can test: <a href="https://gist.github.com/josephspurrier/ec57821bc4a3442a74ca" rel="nofollow">https://gist.github.com/josephspurrier/ec57821bc4a3442a74ca</a></p> <pre><code>2016/02/09 18:41:17 Started ticker 2016/02/09 18:42:00 Tick 2016/02/09 18:43:00 Tick </code></pre></pre>zihua: <pre><p>How about something simple like this? <a href="http://play.golang.org/p/mDYvMTcZjR" rel="nofollow">http://play.golang.org/p/mDYvMTcZjR</a></p></pre>Fwippy: <pre><p>Why do you need it to run at the very beginning of the minute?</p> <p>You can just manually run your first tick; put a <code>ticker &lt;- time.Now()</code> right after you create your ticker.</p></pre>Nooby1990: <pre><p>I guess it does not have to be the start of a minute, but with the systems I am dealing with I would like to define the times and Intervals at least to the specific seconds. If I can schedule a call every Minute at the start of the Minute, then I can also easily schedule other times and Intervals which would help immensely.</p> <p>Sending a Time down the Chanel of the Ticker does seem like a clever solution, but unfortunately I can not send something to the chanel. I can only Receive from it.</p> <pre><code>invalid operation: ticker &lt;- time.Now() (send to receive-only type &lt;-chan time.Time) </code></pre> <p>The Documentation defines the Ticker Chanel like this:</p> <pre><code>C &lt;-chan Time </code></pre> <p>But thank you for this Idea. I would not have thought about just sending something to the Chanel.</p></pre>Fwippy: <pre><p>Ah; sorry about that! I didn&#39;t notice it was receive-only from the spec. You can probably abstract it out to a simple function, and then call that in addition.</p></pre>010a: <pre><p>I can&#39;t think of any cleaner ways. Its a strange problem, and thus is likely to have a strange solution. </p></pre>Nooby1990: <pre><p>Is it really such a strange thing to do? It does not seem that strange to me. I guess people usually use cron or similar solve something like this. Which, unfortunately, I don&#39;t think I can to with this Project.</p></pre>Consuelas-Revenge: <pre><p>Another approach is to just implement your own ticker <a href="https://play.golang.org/p/3VL2_jK46j" rel="nofollow">https://play.golang.org/p/3VL2_jK46j</a></p> <p>It can even be simplified by getting rid of the channels and just call the target code directly.</p></pre>Nooby1990: <pre><p>Implementing my own Ticker is probably the cleanest and nicest solution. Thank you for the suggestion.</p> <p>I don&#39;t think that I want to get rid of the channels since I would need to have tickers for multiple use cases. Or I could get rid of the channels and make a ticker that gets a function as an argument and call that function on every tick. I don&#39;t know yet, I am going to play around with this some more and try out which is better for me.</p> <p>But I am certain that you just set me in the right direction. Thank you.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

586 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传