条件超时
Conditional Timeout
我有一些代码,有3个定时器,
- GracefulExecutionTimeout - 总 运行 时间
- WaitTimeout - 初始等待第一条消息的时间
- IdleTimeout - 等待后续消息的时间
如果达到任何计时器,应用程序应该干净地退出。我让它在下面工作
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)
}
}
我想将 WaitTimeout 设为可选,但不确定如何处理它。如果我用 if
语句包围 waitTimer
的构造,那么它不会工作,因为 waitTimer
没有为 select
语句定义......我怎样才能使 WaitTimeout条件 ?
我可以 .Stop()
计时器创建后,但这看起来有点脏......
您可以在if
语句之外声明等待计时器及其通道,并且仅在需要等待计时器时才初始化它们。如果不是,通道可能会保持其零值——即 nil
——因为从 nil
通道接收永远阻塞,所以这个 case
永远不会准备好(有关详细信息,请参阅 ).
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)
// ...
}
}
那么当然你只能重置等待计时器,如果它存在,这也必须检查(如果它returns false
,不要忘记排空通道):
// stop wait timer if exists
if waitTimer != nil && !waitTimer.Stop() {
<-waitTimerC
}
在 Go Playground 上试用。
我有一些代码,有3个定时器,
- GracefulExecutionTimeout - 总 运行 时间
- WaitTimeout - 初始等待第一条消息的时间
- IdleTimeout - 等待后续消息的时间
如果达到任何计时器,应用程序应该干净地退出。我让它在下面工作
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)
}
}
我想将 WaitTimeout 设为可选,但不确定如何处理它。如果我用 if
语句包围 waitTimer
的构造,那么它不会工作,因为 waitTimer
没有为 select
语句定义......我怎样才能使 WaitTimeout条件 ?
我可以 .Stop()
计时器创建后,但这看起来有点脏......
您可以在if
语句之外声明等待计时器及其通道,并且仅在需要等待计时器时才初始化它们。如果不是,通道可能会保持其零值——即 nil
——因为从 nil
通道接收永远阻塞,所以这个 case
永远不会准备好(有关详细信息,请参阅
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)
// ...
}
}
那么当然你只能重置等待计时器,如果它存在,这也必须检查(如果它returns false
,不要忘记排空通道):
// stop wait timer if exists
if waitTimer != nil && !waitTimer.Stop() {
<-waitTimerC
}
在 Go Playground 上试用。