猿问

基于时间编写睡眠函数。之后

编辑:我的问题与How to write my own Sleep function using just time.After 不同?它有一个不同的代码变体,由于单独的原因而无法正常工作,我需要解释原因。


我正在尝试在这里解决作业问题:https : //www.golang-book.com/books/intro/10(使用编写您自己的睡眠功能time.After)。


到目前为止,这是我基于该章节中讨论的示例所做的尝试:


package main


import (

        "fmt"

        "time"

)


func myOwnSleep(duration int) {

        for {

                select {

                case <-time.After(time.Second * time.Duration(duration)):

                        fmt.Println("slept!")

                default:

                        fmt.Println("Waiting")

                }

        }

}


func main() {

        go myOwnSleep(3)


        var input string

        fmt.Scanln(&input)

}

http://play.golang.org/p/fb3i9KY3DD


我的想法是,infinitefor将继续执行select语句,default直到time.After函数返回的通道说话。当前代码的问题是,后者不会发生,而default语句被无限调用。


我究竟做错了什么?


慕沐林林
浏览 184回答 1
1回答

POPMUISE

在for循环的每次迭代中,select都会执行涉及评估通道操作数的语句。在每次迭代time.After()中将被调用并创建一个新频道!如果持续时间大于0,则该通道尚未准备好接收,因此将执行默认情况。不会再次测试/检查该通道,下一次迭代会创建一个新的通道,该通道将再次未准备好接收,因此default再次选择案例 - 一如既往。解决方案非常简单,但可以在此答案中看到:func Sleep(sec int) {&nbsp; &nbsp; <-time.After(time.Second* time.Duration(sec))}修复您的变体:如果你想让你的变体工作,你必须只创建一个频道(使用time.After()),存储返回的频道值,并始终检查这个频道。如果通道“启动”(从它接收到一个值),你必须从你的函数返回,因为不会从它接收更多的值,所以你的循环将保持无休止!func myOwnSleep(duration int) {&nbsp; &nbsp; ch := time.After(time.Second * time.Duration(duration))&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-ch:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("slept!")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return // MUST RETURN, else endless loop!&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Waiting")&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}请注意,尽管在从通道接收到值之前,此函数不会“休息”,只会无情地执行代码 - 加载一个 CPU 内核。如果只有 1 个 CPU 内核可用runtime.GOMAXPROCS(),这甚至可能会给您带来麻烦(),其他 goroutine(包括将(或将)发送到通道上的值的 goroutine)可能会被阻塞并且永远不会执行。睡眠(例如time.Sleep(time.Millisecond))可以释放 CPU 内核,使其免于无休止的工作(并允许其他 goroutine 运行)。
随时随地看视频慕课网APP

相关分类

Go
我要回答