golang1.23版本之前 Timer Reset方法无法正确使用

2025-01-28 04:50

本文主要是介绍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版本之前 Timer Reset方法无法正确使用
 

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方法无法正确使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153248

相关文章

Pandas使用SQLite3实战

《Pandas使用SQLite3实战》本文主要介绍了Pandas使用SQLite3实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1 环境准备2 从 SQLite3VlfrWQzgt 读取数据到 DataFrame基础用法:读

macOS无效Launchpad图标轻松删除的4 种实用方法

《macOS无效Launchpad图标轻松删除的4种实用方法》mac中不在appstore上下载的应用经常在删除后它的图标还残留在launchpad中,并且长按图标也不会出现删除符号,下面解决这个问... 在 MACOS 上,Launchpad(也就是「启动台」)是一个便捷的 App 启动工具。但有时候,应

JSON Web Token在登陆中的使用过程

《JSONWebToken在登陆中的使用过程》:本文主要介绍JSONWebToken在登陆中的使用过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录JWT 介绍微服务架构中的 JWT 使用结合微服务网关的 JWT 验证1. 用户登录,生成 JWT2. 自定义过滤

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

springboot security使用jwt认证方式

《springbootsecurity使用jwt认证方式》:本文主要介绍springbootsecurity使用jwt认证方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录前言代码示例依赖定义mapper定义用户信息的实体beansecurity相关的类提供登录接口测试提供一

go中空接口的具体使用

《go中空接口的具体使用》空接口是一种特殊的接口类型,它不包含任何方法,本文主要介绍了go中空接口的具体使用,具有一定的参考价值,感兴趣的可以了解一下... 目录接口-空接口1. 什么是空接口?2. 如何使用空接口?第一,第二,第三,3. 空接口几个要注意的坑坑1:坑2:坑3:接口-空接口1. 什么是空接

Tomcat版本与Java版本的关系及说明

《Tomcat版本与Java版本的关系及说明》:本文主要介绍Tomcat版本与Java版本的关系及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat版本与Java版本的关系Tomcat历史版本对应的Java版本Tomcat支持哪些版本的pythonJ

SpringBoot日志配置SLF4J和Logback的方法实现

《SpringBoot日志配置SLF4J和Logback的方法实现》日志记录是不可或缺的一部分,本文主要介绍了SpringBoot日志配置SLF4J和Logback的方法实现,文中通过示例代码介绍的非... 目录一、前言二、案例一:初识日志三、案例二:使用Lombok输出日志四、案例三:配置Logback一