time.afterFunc 的使用

import (
        "fmt"
        "time"
)


func main() {
     t := time.AfterFunc(3 * time.Second, func() {
         fmt.Println("done")
     })
     // time.Sleep(4)
     for {
        select {
            case <- t.C:
                fmt.Println("ok")
                break;
        }
     }
}

上面的代码执行会报错
image.png

想要实现的效果:
按顺序先看到 "done" 再看到 "ok" (并且不想在主线程 time.Sleep)

参考文档:
https://studygolang.com/pkgdoc
image.png

阅读 12.9k
3 个回答

time.AfterFunc 返回的 Timer t 里,t.Cnil源码。它不能通过 <-t.C 来等待到指定时间。

要想知道定时函数执行完了,必须自己主动从定时函数里发信号出来,比如:

package main

import (
        "fmt"
        "time"
)


func main() {
     c := make(chan int)
     time.AfterFunc(3 * time.Second, func() {
         fmt.Println("done")
     c <- 1
     })
     <-c
     fmt.Println("ok")
}

你的for循环中没有函数调用,go runtime都没有机会去调度goroutine,在for里面随便加一个函数调用就行,例如time.Sleep(1*time.Second)

这是Timer的定义,注释里面说了,用time.AfterFunc创建的话,是不会用到C这个chan的,所以你的代码就死锁了

// The Timer type represents a single event.
// When the Timer expires, the current time will be sent on C,
// unless the Timer was created by AfterFunc.
// A Timer must be created with NewTimer or AfterFunc.
type Timer struct {
    C <-chan Time
    r runtimeTimer
}

你可以看下源码,AfterFunc初始化Timer的时候并没有初始化C变量,你可以用Time.NewTimer实现,或者time.Ticker

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题