如何给网站做,住房和城乡建设部网站建造师,网站快速开发平台,wordpress绿色中文主题前言
函数原型为#xff1a;
func AfterFunc(d Duration, f func()) *TimerGo 的 time.AfterFunc 的作用是等待指定的时间间隔#xff0c;然后在它自己的 goroutine 中调用 f。
现在有一个问题#xff0c;我明明调用了 AfterFunc#xff0c;但是它还没调用我指定的函数
func AfterFunc(d Duration, f func()) *TimerGo 的 time.AfterFunc 的作用是等待指定的时间间隔然后在它自己的 goroutine 中调用 f。
现在有一个问题我明明调用了 AfterFunc但是它还没调用我指定的函数程序就退出了。程序如下所示
package mainimport (fmttime
)func main() {time.AfterFunc(5*time.Second, func() {fmt.Println(5s passed)})
}这段代码什么都没打印就结束了。
问题解决
上面的问题看起来像是 main goroutine 退出了程序直接退出还没来得及调用我们指定的函数。
下面就通过源码来看看是不是我们猜测的这样AfterFunc 的源码如下
func AfterFunc(d Duration, f func()) *Timer {t : Timer{r: runtimeTimer{when: when(d),f: goFunc,arg: f,},}startTimer(t.r)return t
}上面的代码很简单先构造一个定时器然后启动定时器。定时器的内容也很好理解在 when: when(d) 时间调用 f: goFunc 函数函数的参数是 arg: f。
when(d) 的值是什么呢
func when(d Duration) int64 {if d 0 {return runtimeNano()}t : runtimeNano() int64(d)if t 0 {t 163 - 1 // math.MaxInt64}return t
}可以看到 when 就是当前时间再加上我们指定的时间间隔。
那 goFunc 又是什么呢
func goFunc(arg any, seq uintptr) {go arg.(func())()
}这个函数的作用就是创建一个 goroutine在 goroutine 内运行 arg 函数。
arg 就是我们传给 AfterFunc 要运行的函数先使用类型断言将其转换成函数然后再运行它。
于是问题就解决了就是因为 main goroutine 先退出了导致程序直接退出还没来得及执行我们指定的打印函数。下面给出两种解决方案
使用 select 替换 AfterFunc
func main() {select {case -time.After(5 * time.Second):func() {fmt.Println(5s passed)}()}
}使用 WaitGroup 等待其他 goroutine 结束
func main() {var wg sync.WaitGroupwg.Add(1)time.AfterFunc(5*time.Second, func() {defer wg.Done()fmt.Println(5s passed)})wg.Wait()
}参考资料
go1.18.10