我有一些代码,有 3 个计时器,
如果达到任何计时器,应用程序应该干净地退出。我让它在下面工作
msgs := make(chan string)
go func() {
time.Sleep(time.Second)
msgs <- "test"
}()
// graceful max execution time
gracefulMaxTimeout := time.Second * time.Duration(10)
gracefulMaxTimer := time.NewTimer(gracefulMaxTimeout)
// idleTimeout
idleTimeout := time.Second * time.Duration(5)
idleTimer := time.NewTimer(idleTimeout)
// waitTimeout
waitTimeout := time.Second * time.Duration(2)
waitTimer := time.NewTimer(waitTimeout)
for {
select {
case <-gracefulMaxTimer.C:
fmt.Println("GracefulMaxExecutionTimeout Reached")
// graceful exit
os.Exit(0)
case <-idleTimer.C:
fmt.Println("IdleTimeout Reached")
// graceful exit
os.Exit(0)
case <-waitTimer.C:
fmt.Println("WaitTimeout Reached")
// graceful exit
os.Exit(0)
case msg := <-msgs:
// stop wait timer
waitTimer.Stop()
fmt.Println(msg)
// Reset idle timer
if !idleTimer.Stop() {
<-idleTimer.C
}
fmt.Println("IdleIimeout Reset")
idleTimer.Reset(idleTimeout)
}
}
Go Playground
我想将 WaitTimeout 设为可选,但不知道如何处理它。如果我围绕
waitTimer
的构造与 if
那么它就不能作为 waitTimer
没有为 select
定义声明...我怎样才能使 WaitTimeout 有条件?我可以
.Stop()
创建后的计时器,但这似乎有点脏...
最佳答案
您可以在 if
之外声明等待计时器及其 channel 。语句,并且仅在需要等待计时器时才初始化它们。如果不是, channel 可能保持其零值——nil
——因为从 nil
接收 channel 永远阻塞,所以这个 case
永远不会准备好(详情见 How does a non initialized channel behave? )。
useWaitTimer := true
var (
waitTimer *time.Timer
waitTimerC <-chan time.Time
)
if useWaitTimer {
waitTimeout := time.Millisecond * time.Duration(500)
waitTimer = time.NewTimer(waitTimeout)
waitTimerC = waitTimer.C
}
// ...
for {
select {
// ...
case <-waitTimerC:
fmt.Println("WaitTimeout Reached")
// graceful exit
os.Exit(0)
// ...
}
}
然后当然你只能重置等待计时器,如果它存在,这也必须检查(如果它返回
false
,不要忘记耗尽 channel ):// stop wait timer if exists
if waitTimer != nil && !waitTimer.Stop() {
<-waitTimerC
}
在 Go Playground 上试用.
关于go - 条件超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61795339/