ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

timeAfter()

2022-08-29 08:02:30  阅读:197  来源: 互联网

标签:timeAfter fmt After timer func time Println


time.After()

1. time.After()官方解释

刚开始学习时,time包里sleep最常用,在学习context时,突然看到一个time.after,首先是time包的定义:

// After waits for the duration to elapse and then sends the current time
// on the returned channel.
// It is equivalent to NewTimer(d).C.
// The underlying Timer is not recovered by the garbage collector
// until the timer fires. If efficiency is a concern, use NewTimer
// instead and call Timer.Stop if the timer is no longer needed.
func After(d Duration) <-chan Time {
    return NewTimer(d).C
}

英文看不懂没关系,来这里翻译一下,这个软件翻译的太准确了!

2. time.After()代码示例

func main() {
	tchan := time.After(time.Second * 3)
	fmt.Printf("tchan type=%T\n", tchan)
	fmt.Println("mark 1")
	for i := 0; i < 10; i++ {
		fmt.Print(i)
	}
	fmt.Println()
	fmt.Println("tchan,", <-tchan)
	fmt.Println("mark 2")

out

tchan type=<-chan time.Time
mark 1
0123456789
tchan, 2022-08-11 21:47:29.7323266 +0800 CST m=+3.002611601 
mark 2

这个例子比较简单,来分析一下

  • 首先调用time.After(duration),此函数马上返回一个time.Time类型的Chan,不阻塞。注意如果是sleep(),就会阻塞了,就不会往下走了,直到时间到了。而After()不会阻塞,后面你该做什么做什么,不影响。
  • 到了duration时间后,自动塞一个当前时间进去。
  • 写了简单的测试的示例代码,放在了这里。go-basic-exercises/timerAfter_test.go

3. AfterFunc()

在学习了After()后,那么在它的基础上,还有一个AfterFunc(),这个可以指定函数在多长时间执行,也不影响做其他事情。而且可以使用stop() 取消执行。这也是一个很好的设计,比如我们可以设置了一个功能函数,定点到10分钟后执行,但是如果发现发生了异常的事情,或者是发现满足了不需要执行这个函数的条件,就可以stop()掉。就如同抗日片中播放的,计划晚上六点攻打,如果检测到环境不对,那就取消攻打计划。

func TestAfter(t *testing.T) {
	timer := time.AfterFunc(time.Second*30, func() {
		fmt.Println("30s到了哦")
	})
	time.Sleep(time.Second * 20)
	timer.Stop()
	time.Sleep(time.Minute)
}

有意思的是,我在调试程序中,没有设置阻塞时间,程序一下子就运行完成了,如果不设置延时,主goroutine结束了,它也结束了。举一个例子,我设置下午两点的闹钟,这是不是一下子就设置完了,这可以当成函数的声明,只是告诉你到了这个点要做这个事情,但是如果你不延时,阻塞主goroutine,就好像你让手机两点叫你起床,但是你又没等到那个时间把手机关机了,这个时候当然不会执行这个动作了。下面是更形象的例子:

var notify bool

func main() {
	timer := time.AfterFunc(30*time.Millisecond, func() {
		fmt.Println("30ms到了哦,我开始执行啦...")
	})
	fmt.Println("等待到时执行函数,我去忙其他事情...")
	time.Sleep(20 * time.Millisecond)
	notify = true
	if notify {
		timer.Stop()
		fmt.Println("收到通知,情况有变,任务取消")
	}
	time.Sleep(50 * time.Millisecond)
}

out

等待到时执行函数,我去忙其他事情...
收到通知,情况有变,任务取消

4. 总结

  • sleep() 和 after() 底层,应该实现是差不多的,有时间可以分析一下它们源码,看看实现方式的差异。after()在Go中确实是一个很好的设计。sleep() 会阻塞,而after() 不会影响后面的运行。
  • 在异步场景中,尤其是context等,基本上都是返回 channel,然后在一个必要的地方用 select case 来监听。

标签:timeAfter,fmt,After,timer,func,time,Println
来源: https://www.cnblogs.com/sunnybowen/p/16634679.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有