go - 如何在 Golang 中使用 'time.After' 和 'default'?

标签 go goroutine

我正在尝试理解 Golang 例程的简单代码:

package main

import (
    "fmt"
    "time"
)

func sleep(seconds int, endSignal chan<- bool) {
    time.Sleep(time.Duration(seconds) * time.Second)
    endSignal <- true
}

func main() {
    endSignal := make(chan bool, 1)
    go sleep(3, endSignal)
    var end bool

    for !end {
        select {
        case end = <-endSignal:
            fmt.Println("The end!")
        case <-time.After(5 * time.Second):
            fmt.Println("There's no more time to this. Exiting!")
            end = true
        }
    }

}

很好,但是为什么我不能在这个“选择” block 中使用简单的默认值?像这样:

for !end {
    select {
    case end = <-endSignal:
        fmt.Println("The end.")
    case <-time.After(4 * time.Second):
        fmt.Println("There's no more time to this. Exiting!")
        end = true
    default:
        fmt.Println("No end signal received.")
    }
}

它得到这个输出:

❯ go run goroutines-timeout.go
No end signal received!
No end signal received!
No end signal received!
No end signal received!
...
The end!

我不明白为什么。

最佳答案

每次执行 time.After(4 * time.Second) 都会创建一个新的计时器 channel 。 select 语句不可能记住它在上一次迭代中选择的 channel 。您还采取了一个异步操作并将其变成一个繁忙的循环,从而破坏了 select 语句的目的。

您所需要的只是围绕您感兴趣的两个 channel 进行简单选择。它根本不需要循环。

select {
case <-endSignal:
    fmt.Println("The end!")
case <-time.After(4 * time.Second):
    fmt.Println("There's no more time to this. Exiting!")
}

https://play.golang.org/p/jb4EE8e6cw

如果你真的想轮询多次,把定时器放在for循环之外,这样每次迭代都会检查同一个定时器

timeout := time.After(5 * time.Second)
pollInt := time.Second

for {
    select {
    case <-endSignal:
        fmt.Println("The end!")
        return
    case <-timeout:
        fmt.Println("There's no more time to this. Exiting!")
        return
    default:
        fmt.Println("still waiting")
    }
    time.Sleep(pollInt)
}

关于go - 如何在 Golang 中使用 'time.After' 和 'default'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39212333/

相关文章:

go - 如何避免这个 golang 程序中的死锁?

go - 即使没有竞争条件也没有得到任何输出

Goroutine 在 Windows 和 Linux 上的行为不同

go - Go 中的并发例程

go - 在 new func 中运行 goroutine 或不在 recover 之间的区别

serialization - Golang 映射/数组(非结构)序列化

go - 整数映射 -> Go 中的 2d slice

go - 为什么我需要在单独的 go 例程中使用 wg.Wait() 和 close() ?

mongodb - Golang 从 MongoDB 的嵌套 json 数据映射中找到一个值

debugging - 无法在 IntelliJ 中调试 Go 应用程序