使用 ctrl+c 退出的带有时间指示器的及时轮询控制台应用程序
Timely polling console app with time indicator that exits on ctrl+c
我想及时汇集代币。令牌本身也获得了有关何时过期的信息。
这应该 运行 永远,直到用户输入 ctrl+c。
我用
做了同样的尝试
span := timeLeft(*expDate)
timer := time.NewTimer(span).C
ticker := time.NewTicker(time.Second * 5).C
这也不起作用(应用程序在倒计时后挂起)。所以我决定尝试 <- time.After(...)
我的代码不起作用。您会看到倒计时,但它不会在过期时中断。
为了简单起见,这是一个带有轮询逻辑的小摘录 main.go:
func refreshToken() (time.Time, error) {
//This should simulate a http request and returns the new target date for the next refresh
time.Sleep(2 * time.Second)
return time.Now().Add(10 * time.Second), nil
}
func timeLeft(d time.Time) time.Duration {
exactLeft := d.Sub(time.Now())
floorSeconds := math.Floor(exactLeft.Seconds())
return time.Duration(floorSeconds) * time.Second
}
func poller(expDate *time.Time) {
exp := timeLeft(*expDate)
done := make(chan bool)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
for {
select {
// print time left on the screen
case <-time.After(3 * time.Second):
go func() {
fmt.Printf("\rNext Token refresh will be in: %v", timeLeft(*expDate))
}()
// mark as done when date is due
case <-time.After(exp):
fmt.Println("Refresh token now!")
done <- true
// exit app
case <-c:
os.Exit(0)
break
// exit function when done
case <-done:
break
}
}
}
func main() {
var expiration time.Time
expiration = time.Now().Add(10 * time.Second)
// loop and refresh token as long as the app does not exit
for {
poller(&expiration)
ex, err := refreshToken()
expiration = ex
if err != nil {
panic(err)
}
fmt.Println("next round poller")
}
}
我也不确定我是否需要 done 频道?
监听两个定时器并调用自身直到有人按下 ctrl+c 需要什么?
找到解决办法。虽然 @ain 对缓冲完成通道的理解是正确的,但现在代码中并不真正需要它。没有它也能工作。
这个技巧确实在 for 循环之外有 timer
,在循环内部有 ticker
。原因是 time.After
是一个 func
那 return 每次迭代都是一个新频道。这个接缝对于自动收报机来说非常好,但对于 timer
就不行了。
通过以下更改,它起作用了 =) ...
func poller(expDate *time.Time) {
exp := timeLeft(*expDate)
timer := time.After(exp)
fmt.Printf("Next Token refresh will be in: %v\n", exp)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
for {
select {
// print time left on the screen
case <-time.After(3 * time.Second):
go func() {
fmt.Printf("\r ")
fmt.Printf("\r%v", timeLeft(*expDate))
}()
// mark as done when date is due
case <-timer:
fmt.Println("Refresh token now!")
return
// exit app
case <-c:
os.Exit(0)
break
}
}
}
我想及时汇集代币。令牌本身也获得了有关何时过期的信息。 这应该 运行 永远,直到用户输入 ctrl+c。
我用
做了同样的尝试span := timeLeft(*expDate)
timer := time.NewTimer(span).C
ticker := time.NewTicker(time.Second * 5).C
这也不起作用(应用程序在倒计时后挂起)。所以我决定尝试 <- time.After(...)
我的代码不起作用。您会看到倒计时,但它不会在过期时中断。
为了简单起见,这是一个带有轮询逻辑的小摘录 main.go:
func refreshToken() (time.Time, error) {
//This should simulate a http request and returns the new target date for the next refresh
time.Sleep(2 * time.Second)
return time.Now().Add(10 * time.Second), nil
}
func timeLeft(d time.Time) time.Duration {
exactLeft := d.Sub(time.Now())
floorSeconds := math.Floor(exactLeft.Seconds())
return time.Duration(floorSeconds) * time.Second
}
func poller(expDate *time.Time) {
exp := timeLeft(*expDate)
done := make(chan bool)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
for {
select {
// print time left on the screen
case <-time.After(3 * time.Second):
go func() {
fmt.Printf("\rNext Token refresh will be in: %v", timeLeft(*expDate))
}()
// mark as done when date is due
case <-time.After(exp):
fmt.Println("Refresh token now!")
done <- true
// exit app
case <-c:
os.Exit(0)
break
// exit function when done
case <-done:
break
}
}
}
func main() {
var expiration time.Time
expiration = time.Now().Add(10 * time.Second)
// loop and refresh token as long as the app does not exit
for {
poller(&expiration)
ex, err := refreshToken()
expiration = ex
if err != nil {
panic(err)
}
fmt.Println("next round poller")
}
}
我也不确定我是否需要 done 频道? 监听两个定时器并调用自身直到有人按下 ctrl+c 需要什么?
找到解决办法。虽然 @ain 对缓冲完成通道的理解是正确的,但现在代码中并不真正需要它。没有它也能工作。
这个技巧确实在 for 循环之外有 timer
,在循环内部有 ticker
。原因是 time.After
是一个 func
那 return 每次迭代都是一个新频道。这个接缝对于自动收报机来说非常好,但对于 timer
就不行了。
通过以下更改,它起作用了 =) ...
func poller(expDate *time.Time) {
exp := timeLeft(*expDate)
timer := time.After(exp)
fmt.Printf("Next Token refresh will be in: %v\n", exp)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
for {
select {
// print time left on the screen
case <-time.After(3 * time.Second):
go func() {
fmt.Printf("\r ")
fmt.Printf("\r%v", timeLeft(*expDate))
}()
// mark as done when date is due
case <-timer:
fmt.Println("Refresh token now!")
return
// exit app
case <-c:
os.Exit(0)
break
}
}
}