条件超时

Conditional Timeout

我有一些代码,有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 设为可选,但不确定如何处理它。如果我用 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 上试用。