根据时间写睡眠功能.之后

par*_*iss 1 time sleep channel go

编辑:我的问题不同于如何使用时间编写我自己的睡眠功能.后?它有一个不同的代码变体,由于一个单独的原因不起作用,我需要解释为什么.

我正在尝试解决这里的作业问题: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)
}
Run Code Online (Sandbox Code Playgroud)

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

我的思维过程是无限for将继续执行select语句,default直到time.After函数的返回通道会话.当前代码存在问题,后者不会发生,而default语句被无限调用.

我究竟做错了什么?

icz*_*cza 5

for循环的每次迭代中,select执行语句,包括评估通道操作数.

在每次迭代中time.After()都会调用并创建一个新的通道!

如果持续时间超过0,则此通道尚​​未准备好接收,因此将执行默认情况.此通道不会再次测试/检查,下一次迭代会创建一个新的通道,该通道将再次无法接收,因此default再次选择该情况 - 一如既往.

解决方案非常简单,但在这个答案中可以看出:

func Sleep(sec int) {
    <-time.After(time.Second* time.Duration(sec))
}
Run Code Online (Sandbox Code Playgroud)

修复你的变种:

如果要使变体工作,则必须仅创建一个通道(使用time.After()),存储返回的通道值,并始终检查此通道.如果频道"开始"(从中收到一个值),你必须从你的函数返回,因为不会从它接收更多的值,所以你的循环将保持无穷无尽!

func myOwnSleep(duration int) {
    ch := time.After(time.Second * time.Duration(duration))
    for {
        select {
        case <-ch:
            fmt.Println("slept!")
            return // MUST RETURN, else endless loop!
        default:
            fmt.Println("Waiting")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,虽然直到从通道接收到一个值,但此函数不会"休息"并且只是无情地执行代码 - 加载一个CPU内核.如果只有1个CPU内核可用(runtime.GOMAXPROCS()),这甚至可能会给您带来麻烦,其他goroutine(包括将(或将会)在通道上发送值的goroutine可能会被阻止并且永远不会被执行.休眠(例如time.Sleep(time.Millisecond))可以释放CPU核心进行无休止的工作(并允许其他goroutine运行).