本文主要是介绍golang1.23版本之前 Timer Reset方法无法正确使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《golang1.23版本之前TimerReset方法无法正确使用》在Go1.23之前,使用`time.Reset`函数时需要先调用`Stop`并明确从timer的channel中抽取出东西,以避...
golang1.23 之前 Reset 到底有什么问题
在 golang 的 time.Reset 文档中有这么一句话,为了防止文档更新而导致内容变动,这里粘贴出来:
Before Go 1.23, the only safe way to use Reset was to [Stop] and explicitly drain the timer first. See the NewTimer documentation for more details. 在Go 1.23 之前,唯一安全使用Reset函数的方式是:在使用之前调用Stop函数并且明确的从timer的channel中抽取出东西。
虽然文档中已经告诉了正确使用的方式,但是实际上在真正的代码中无法达到这个要求,参考下方代码(来源代码来源):
//consumer go func() { // try to read from channel, block at most 5s. // if timeout, print time event and go on loop. // if read a message which is not the type we want(we want true, not false), // retry to read. timer := time.NewTimer(time.Second * 5) for { // timer may be not active, and fireandroidd if !timer.Stop() { select { case <-timer.C: //try to drain from the channel,尝试抽取,由于使用select,因此这里可以保证:不阻塞 + 一定抽取成功 php default: } } timer.Reset(time.Second * 5) //重置定时器 select { case b := <-c: if b == false { fmt.Println(time.Now(), ":recv false. continue") continue } //we want true, not false fmt.Println(time.Now(), ":recv true. return") return case <-timer.C: fmt.Println(time.Now(), ":timer expired") continue } } }()
在上面的代码中,我们按照文档的要求,在 timer.Reset 之前已经调用了 Stop 函数,且如果 Stop 成功(返回 true),还尝试抽取 timer,看起来似乎没问题的代码中仍然存在问题。
问题的关键在于:当 Ticket 触发的时候,设置定时器状态的操作和发送 channel 的操作并不是原子的,见 runOneTimer 函数。
异常情况:尝试抽取 channel 在 发送 channel 之前,这样会导致 Reset 之前并没有真正的清空 timer,后一次的 timer.C 还没到触发时间就异常的触发了!
golang1.23 之前到底应该如何正确的使用 Reset
实际上简洁点就这么写,每次一个新的局部变量 Timer 结构体没压力,非要复用使用 Reset 的可读性太差了,对维护者不友好,而且习惯了不好的写法,哪天一不小心就写出问题了~
go func() { for { func() { timer := time.NewjavascriptTimer(time.Second * 2) defer timer.Stop() select { case b := <-c: if !b { fmt.Println(time.Now(), "work...") } case <-timer.C: // BBB: normal receive from channel timeout event fmt.Println(time.Now(), "timeout") } }() } }()
参考:
https://tonybai.com/2016/12/21/how-to-use-timer-reset-in-golang-correctly/
https:/编程/www.v2ex.com/t/794283
到此这篇关于golang1.23版本之前 Timer ReseChina编程t方法无法正确使用的文章就介绍到这了,更多相关golang Timer Reset方法无法正确使用内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!
这篇关于golang1.23版本之前 Timer Reset方法无法正确使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!