在Golang中实现类似定时器的闹钟功能

huangapple go评论121阅读模式
英文:

Alarm like timer functionality in Golang

问题

有没有一种在Golang中设计一个在特定未来时间到期的定时器的方法?我的意思是一个在凌晨2点到期的定时器(假设当前时间是凌晨12点)。我知道一种方法是使用

  1. timer(target_future_time - current_time)

但这似乎不是一个准确的方法(在考虑执行时间时可能不准确)。有人可以帮忙吗?

英文:

Is there any way for designing a timer that expires on a specific future time in Golang ? I mean a timer that expires on 2AM (let the current time be 12AM). I know one way is to use,

  1. timer(target_future_time - current_time)

but doesn't seem to be an exact way of doing it (may not be accurate on considering the execution time). Can anyone help please?

答案1

得分: 2

在golang中,可能有两种方法创建ticker,就像下面的代码一样:

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func main() {
  7. //第一种实现方式
  8. ticker1 := time.NewTicker(1 * time.Second)
  9. i := 1
  10. for c := range ticker1.C {
  11. i++
  12. fmt.Println(c.Format("2006/01/02 15:04:05.999999999"))
  13. if i > 5 {
  14. ticker1.Stop()
  15. break
  16. }
  17. }
  18. fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"), " 1 Finished.")
  19. //第二种实现方式
  20. i = 1
  21. ticker2 := time.AfterFunc(1*time.Second, func() {
  22. i++
  23. fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"))
  24. })
  25. for {
  26. select {
  27. case <-ticker2.C:
  28. fmt.Println("nsmei")
  29. case <-time.After(3 * time.Second):
  30. if i <= 5 {
  31. ticker2.Reset(1 * time.Second)
  32. continue
  33. }
  34. goto BRK
  35. }
  36. BRK:
  37. ticker2.Stop()
  38. break
  39. }
  40. fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"), " 2 Finished.")
  41. }

输出结果:

  1. 2016/01/26 16:46:34.261248567
  2. 2016/01/26 16:46:35.256381743
  3. 2016/01/26 16:46:36.259717152
  4. 2016/01/26 16:46:37.260320837
  5. 2016/01/26 16:46:38.259312704
  6. 2016/01/26 16:46:38.259410752 1 Finished.
  7. 2016/01/26 16:46:39.260604274
  8. 2016/01/26 16:46:42.261091322
  9. 2016/01/26 16:46:45.263136257
  10. 2016/01/26 16:46:48.264193517
  11. 2016/01/26 16:46:51.265655137
  12. 2016/01/26 16:46:53.265722632 2 Finished.
  13. 根据执行结果,第一种方法比第二种方法更精确。
  14. 在你的情况下,你可以使用`time.Time.Sub()`来计算持续时间,并使用第二种方法执行一次,其余使用第一种方法。
  15. 希望这些对你有帮助!
  16. <details>
  17. <summary>英文:</summary>
  18. &lt;p&gt;In golang,maybe there are two way create ticker,just like the following:&lt;/p&gt;
  19. package main
  20. import (
  21. &quot;fmt&quot;
  22. &quot;time&quot;
  23. )
  24. func main() {
  25. //第一种实现方式
  26. ticker1 := time.NewTicker(1 * time.Second)
  27. i := 1
  28. for c := range ticker1.C {
  29. i++
  30. fmt.Println(c.Format(&quot;2006/01/02 15:04:05.999999999&quot;))
  31. if i &gt; 5 {
  32. ticker1.Stop()
  33. break
  34. }
  35. }
  36. fmt.Println(time.Now().Format(&quot;2006/01/02 15:04:05.999999999&quot;), &quot; 1 Finished.&quot;)
  37. //第二种实现方式
  38. i = 1
  39. ticker2 := time.AfterFunc(1*time.Second, func() {
  40. i++
  41. fmt.Println(time.Now().Format(&quot;2006/01/02 15:04:05.999999999&quot;))
  42. })
  43. for {
  44. select {
  45. case &lt;-ticker2.C:
  46. fmt.Println(&quot;nsmei&quot;)
  47. case &lt;-time.After(3 * time.Second):
  48. if i &lt;= 5 {
  49. ticker2.Reset(1 * time.Second)
  50. continue
  51. }
  52. goto BRK
  53. }
  54. BRK:
  55. ticker2.Stop()
  56. break
  57. }
  58. fmt.Println(time.Now().Format(&quot;2006/01/02 15:04:05.999999999&quot;), &quot; 2 Finished.&quot;)
  59. }
  60. Output:
  61. 2016/01/26 16:46:34.261248567
  62. 2016/01/26 16:46:35.256381743
  63. 2016/01/26 16:46:36.259717152
  64. 2016/01/26 16:46:37.260320837
  65. 2016/01/26 16:46:38.259312704
  66. 2016/01/26 16:46:38.259410752 1 Finished.
  67. 2016/01/26 16:46:39.260604274
  68. 2016/01/26 16:46:42.261091322
  69. 2016/01/26 16:46:45.263136257
  70. 2016/01/26 16:46:48.264193517
  71. 2016/01/26 16:46:51.265655137
  72. 2016/01/26 16:46:53.265722632 2 Finished.
  73. **According to the execution,the first is more precise than the second.**&lt;p&gt;In your case,you can use &lt;code&gt;time.Time.Sub()&lt;/code&gt; to calculate the duration,and execute once using the second method,the rest using the first method.&lt;/p&gt;
  74. &lt;p&gt;I hope these help you!&lt;/p&gt;
  75. </details>
  76. # 答案2
  77. **得分**: 0
  78. 以下是实现你的目的的代码。你只需要按照下面 main() 函数中所示的方式调用 ScheduleAlarm()。
  79. ```go
  80. package main
  81. import (
  82. "strings"
  83. "strconv"
  84. "fmt"
  85. "time"
  86. )
  87. // 表示时间的结构体。
  88. type Time struct {
  89. Hh int // 小时。
  90. Mm int // 分钟。
  91. Ss int // 秒。
  92. }
  93. func main() {
  94. /*
  95. 按照下面所示的方式设置闹钟。
  96. 时间必须以24小时制格式指定。
  97. 同时,传递在闹钟触发后要调用的回调函数。
  98. */
  99. alarm := ScheduleAlarm(Time{23, 28, 0}, func() {
  100. fmt.Println("收到闹钟")
  101. })
  102. // 做你的事情。
  103. for i := 0; i < 10; i++ {
  104. fmt.Println(i)
  105. time.Sleep(2 * time.Second)
  106. }
  107. // 不要忘记在需要阻塞的时候调用下面的代码。
  108. <-alarm
  109. }
  110. // 调用此函数来设置闹钟。在闹钟触发后,将调用回调函数。
  111. func ScheduleAlarm(alarmTime Time, callback func() ()) (endRecSignal chan string) {
  112. endRecSignal = make(chan string)
  113. go func() {
  114. timeSplice := strings.Split(time.Now().Format("15:04:05"), ":")
  115. hh, _ := strconv.Atoi(timeSplice[0])
  116. mm, _ := strconv.Atoi(timeSplice[1])
  117. ss, _ := strconv.Atoi(timeSplice[2])
  118. startAlarm := GetDiffSeconds(Time{hh, mm, ss}, alarmTime)
  119. // 设置闹钟。
  120. time.AfterFunc(time.Duration(startAlarm) * time.Second, func() {
  121. callback()
  122. endRecSignal <- "录音完成"
  123. close(endRecSignal)
  124. })
  125. }()
  126. return
  127. }
  128. func GetDiffSeconds(fromTime, toTime Time) int {
  129. fromSec := GetSeconds(fromTime)
  130. toSec := GetSeconds(toTime)
  131. diff := toSec - fromSec
  132. if diff < 0 {
  133. return diff + 24 * 60 * 60
  134. } else {
  135. return diff
  136. }
  137. }
  138. func GetSeconds(time Time) int {
  139. return time.Hh * 60 * 60 + time.Mm * 60 + time.Ss
  140. }

希望对你有所帮助。

英文:

The following code achieves your purpose. All you've to do is call ScheduleAlarm() in the manner shown in the main() function below.

  1. package main
  2. import (
  3. &quot;strings&quot;
  4. &quot;strconv&quot;
  5. &quot;fmt&quot;
  6. &quot;time&quot;
  7. )
  8. // A struct for representing time.
  9. type Time struct {
  10. Hh int // Hours.
  11. Mm int // Minutes.
  12. Ss int // Seconds.
  13. }
  14. func main() {
  15. /*
  16. Set the alarm as shown below.
  17. Time must be specified in 24 hour clock format.
  18. Also, pass the callback to be called after the alarm is triggered.
  19. */
  20. alarm := ScheduleAlarm(Time{23, 28, 0}, func() {
  21. fmt.Println(&quot;alarm received&quot;)
  22. })
  23. // Do your stuff.
  24. for i := 0; i &lt; 10; i++ {
  25. fmt.Println(i)
  26. time.Sleep(2 * time.Second)
  27. }
  28. // Don&#39;t forget to call the below line whenever you want to block.
  29. &lt;-alarm
  30. }
  31. // Call this function to schedule the alarm. The callback will be called after the alarm is triggered.
  32. func ScheduleAlarm(alarmTime Time, callback func() ()) (endRecSignal chan string) {
  33. endRecSignal = make(chan string)
  34. go func() {
  35. timeSplice := strings.Split(time.Now().Format(&quot;15:04:05&quot;), &quot;:&quot;)
  36. hh, _ := strconv.Atoi(timeSplice[0])
  37. mm, _ := strconv.Atoi(timeSplice[1])
  38. ss, _ := strconv.Atoi(timeSplice[2])
  39. startAlarm := GetDiffSeconds(Time{hh, mm, ss}, alarmTime)
  40. // Setting alarm.
  41. time.AfterFunc(time.Duration(startAlarm) * time.Second, func() {
  42. callback()
  43. endRecSignal &lt;- &quot;finished recording&quot;
  44. close(endRecSignal)
  45. })
  46. }()
  47. return
  48. }
  49. func GetDiffSeconds(fromTime, toTime Time) int {
  50. fromSec := GetSeconds(fromTime)
  51. toSec := GetSeconds(toTime)
  52. diff := toSec - fromSec
  53. if diff &lt; 0 {
  54. return diff + 24 * 60 * 60
  55. } else {
  56. return diff
  57. }
  58. }
  59. func GetSeconds(time Time) int {
  60. return time.Hh * 60 * 60 + time.Mm * 60 + time.Ss
  61. }

Hope this helps.

huangapple
  • 本文由 发表于 2016年1月26日 15:51:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/35009070.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定