英文:
Alarm like timer functionality in Golang
问题
有没有一种在Golang中设计一个在特定未来时间到期的定时器的方法?我的意思是一个在凌晨2点到期的定时器(假设当前时间是凌晨12点)。我知道一种方法是使用
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,
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,就像下面的代码一样:
package main
import (
"fmt"
"time"
)
func main() {
//第一种实现方式
ticker1 := time.NewTicker(1 * time.Second)
i := 1
for c := range ticker1.C {
i++
fmt.Println(c.Format("2006/01/02 15:04:05.999999999"))
if i > 5 {
ticker1.Stop()
break
}
}
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"), " 1 Finished.")
//第二种实现方式
i = 1
ticker2 := time.AfterFunc(1*time.Second, func() {
i++
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"))
})
for {
select {
case <-ticker2.C:
fmt.Println("nsmei")
case <-time.After(3 * time.Second):
if i <= 5 {
ticker2.Reset(1 * time.Second)
continue
}
goto BRK
}
BRK:
ticker2.Stop()
break
}
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"), " 2 Finished.")
}
输出结果:
2016/01/26 16:46:34.261248567
2016/01/26 16:46:35.256381743
2016/01/26 16:46:36.259717152
2016/01/26 16:46:37.260320837
2016/01/26 16:46:38.259312704
2016/01/26 16:46:38.259410752 1 Finished.
2016/01/26 16:46:39.260604274
2016/01/26 16:46:42.261091322
2016/01/26 16:46:45.263136257
2016/01/26 16:46:48.264193517
2016/01/26 16:46:51.265655137
2016/01/26 16:46:53.265722632 2 Finished.
根据执行结果,第一种方法比第二种方法更精确。
在你的情况下,你可以使用`time.Time.Sub()`来计算持续时间,并使用第二种方法执行一次,其余使用第一种方法。
希望这些对你有帮助!
<details>
<summary>英文:</summary>
<p>In golang,maybe there are two way create ticker,just like the following:</p>
package main
import (
"fmt"
"time"
)
func main() {
//第一种实现方式
ticker1 := time.NewTicker(1 * time.Second)
i := 1
for c := range ticker1.C {
i++
fmt.Println(c.Format("2006/01/02 15:04:05.999999999"))
if i > 5 {
ticker1.Stop()
break
}
}
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"), " 1 Finished.")
//第二种实现方式
i = 1
ticker2 := time.AfterFunc(1*time.Second, func() {
i++
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"))
})
for {
select {
case <-ticker2.C:
fmt.Println("nsmei")
case <-time.After(3 * time.Second):
if i <= 5 {
ticker2.Reset(1 * time.Second)
continue
}
goto BRK
}
BRK:
ticker2.Stop()
break
}
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"), " 2 Finished.")
}
Output:
2016/01/26 16:46:34.261248567
2016/01/26 16:46:35.256381743
2016/01/26 16:46:36.259717152
2016/01/26 16:46:37.260320837
2016/01/26 16:46:38.259312704
2016/01/26 16:46:38.259410752 1 Finished.
2016/01/26 16:46:39.260604274
2016/01/26 16:46:42.261091322
2016/01/26 16:46:45.263136257
2016/01/26 16:46:48.264193517
2016/01/26 16:46:51.265655137
2016/01/26 16:46:53.265722632 2 Finished.
**According to the execution,the first is more precise than the second.**<p>In your case,you can use <code>time.Time.Sub()</code> to calculate the duration,and execute once using the second method,the rest using the first method.</p>
<p>I hope these help you!</p>
</details>
# 答案2
**得分**: 0
以下是实现你的目的的代码。你只需要按照下面 main() 函数中所示的方式调用 ScheduleAlarm()。
```go
package main
import (
"strings"
"strconv"
"fmt"
"time"
)
// 表示时间的结构体。
type Time struct {
Hh int // 小时。
Mm int // 分钟。
Ss int // 秒。
}
func main() {
/*
按照下面所示的方式设置闹钟。
时间必须以24小时制格式指定。
同时,传递在闹钟触发后要调用的回调函数。
*/
alarm := ScheduleAlarm(Time{23, 28, 0}, func() {
fmt.Println("收到闹钟")
})
// 做你的事情。
for i := 0; i < 10; i++ {
fmt.Println(i)
time.Sleep(2 * time.Second)
}
// 不要忘记在需要阻塞的时候调用下面的代码。
<-alarm
}
// 调用此函数来设置闹钟。在闹钟触发后,将调用回调函数。
func ScheduleAlarm(alarmTime Time, callback func() ()) (endRecSignal chan string) {
endRecSignal = make(chan string)
go func() {
timeSplice := strings.Split(time.Now().Format("15:04:05"), ":")
hh, _ := strconv.Atoi(timeSplice[0])
mm, _ := strconv.Atoi(timeSplice[1])
ss, _ := strconv.Atoi(timeSplice[2])
startAlarm := GetDiffSeconds(Time{hh, mm, ss}, alarmTime)
// 设置闹钟。
time.AfterFunc(time.Duration(startAlarm) * time.Second, func() {
callback()
endRecSignal <- "录音完成"
close(endRecSignal)
})
}()
return
}
func GetDiffSeconds(fromTime, toTime Time) int {
fromSec := GetSeconds(fromTime)
toSec := GetSeconds(toTime)
diff := toSec - fromSec
if diff < 0 {
return diff + 24 * 60 * 60
} else {
return diff
}
}
func GetSeconds(time Time) int {
return time.Hh * 60 * 60 + time.Mm * 60 + time.Ss
}
希望对你有所帮助。
英文:
The following code achieves your purpose. All you've to do is call ScheduleAlarm() in the manner shown in the main() function below.
package main
import (
"strings"
"strconv"
"fmt"
"time"
)
// A struct for representing time.
type Time struct {
Hh int // Hours.
Mm int // Minutes.
Ss int // Seconds.
}
func main() {
/*
Set the alarm as shown below.
Time must be specified in 24 hour clock format.
Also, pass the callback to be called after the alarm is triggered.
*/
alarm := ScheduleAlarm(Time{23, 28, 0}, func() {
fmt.Println("alarm received")
})
// Do your stuff.
for i := 0; i < 10; i++ {
fmt.Println(i)
time.Sleep(2 * time.Second)
}
// Don't forget to call the below line whenever you want to block.
<-alarm
}
// Call this function to schedule the alarm. The callback will be called after the alarm is triggered.
func ScheduleAlarm(alarmTime Time, callback func() ()) (endRecSignal chan string) {
endRecSignal = make(chan string)
go func() {
timeSplice := strings.Split(time.Now().Format("15:04:05"), ":")
hh, _ := strconv.Atoi(timeSplice[0])
mm, _ := strconv.Atoi(timeSplice[1])
ss, _ := strconv.Atoi(timeSplice[2])
startAlarm := GetDiffSeconds(Time{hh, mm, ss}, alarmTime)
// Setting alarm.
time.AfterFunc(time.Duration(startAlarm) * time.Second, func() {
callback()
endRecSignal <- "finished recording"
close(endRecSignal)
})
}()
return
}
func GetDiffSeconds(fromTime, toTime Time) int {
fromSec := GetSeconds(fromTime)
toSec := GetSeconds(toTime)
diff := toSec - fromSec
if diff < 0 {
return diff + 24 * 60 * 60
} else {
return diff
}
}
func GetSeconds(time Time) int {
return time.Hh * 60 * 60 + time.Mm * 60 + time.Ss
}
Hope this helps.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论