Go AfterFunc 不触发

前言

函数原型为:

func AfterFunc(d Duration, f func()) *Timer

Go 的 time.AfterFunc 的作用是等待指定的时间间隔,然后在它自己的 goroutine 中调用 f

现在有一个问题,我明明调用了 AfterFunc,但是它还没调用我指定的函数,程序就退出了。程序如下所示:

package mainimport ("fmt""time"
)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 = 1<<63 - 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/26676.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FPGA+金融|硬件行情加速系统 打造极速交易场景

会议时间&#xff1a;2024年06月20日&#xff08;周四&#xff09;下午13:50 FPGA金融|硬件行情加速系统 打造极速交易场景_中科亿海微_芯有灵犀 智创未来

Python学习笔记12 -- 有关布尔值的详细说明

一、布尔表达式 最终值为true 或者false 二、常见形式&#xff1a; 1、常量&#xff1a;true false 2、比较运算&#xff1a; and &#xff01; 3、复合运算&#xff1a; and and or 4、其他 例&#xff1a;检测闰年&#xff1a; def specialYearMine(year):if (year%4 …

Elasticsearch集群运维,重平衡、分片、宕节点、扩容

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 参考 探索集群 Elasticsearch 中文文档 https://www.elastic.co/guide/en/elasticsearch/reference…

方差,标准差,CPK指标数据分析 (使用SQL做数据分析)

以下SQL语句&#xff0c;使用sqlserver数据库 方差的计算公式为&#xff1a; 方差 [(x1 - 平均数)^2 (x2 - 平均数)^2 … (xn - 平均数)^2] / n 其中 x1、x2、…、xn 是样本中的各个数据&#xff0c;n 是样本数量。 SELECT AVG(valu) AS avg_valu,COUNT(valu) AS cnt,SUM…

STM32高级控制定时器(STM32F103):TIM1和TIM8介绍

目录 概述 1 认识TIM1和TIM8 2 TIM1和TIM8的特性 3 TIM1和TIM6时基和分频 3.1 时基单元 3.2 预分频 3.3 时基和分频相关寄存器 3.3.1TIMx_CR1 3.3.2 TIMx_PSC 概述 本文主要介绍STM32高级定时器TIM1和TIM8的功能&#xff0c;还介绍了与之相关的寄存器的配置参数。包括…

SPOOL

-----How to Pass UNIX Variable to SPOOL Command (Doc ID 1029440.6) setenv只有csh才有不行啊PROBLEM DESCRIPTION: You would like to put a file name in Unix and have SQL*Plus read that file name, instead of hardcoding it, because it will change.You want to pa…

快速排序 -非递归版-双指针版

个人主页点这里~ 非递归法: 快速排序的非递归实现涉及到使用一个栈来模拟递归调用栈。 因为递归调用内存的栈区一般只有8M,如果数据很多则容易栈溢出(不过现在硬件基本不会),而使用数据结构的栈来模拟实现递归是调用堆区,一般右2G. //得到key int QuickSort1(int* a, int lef…

Sui Bridge在测试网上线并推出10万SUI激励计划

是一种为Sui设计的原生桥接协议&#xff0c;专门用于在Sui与其他网络之间桥接资产和数据。今天&#xff0c;Sui Bridge宣布在测试网上线。作为一种原生协议&#xff0c;Sui Bridge能够在Ethereum和Sui之间轻松且安全地转移ETH、wBTC、USDC和USDT&#xff0c;使其成为Sui基础设施…

如果R是唯一析因整环,那么R[x]也是唯一析因整环

【定义1】商域 如果 R R R是整环&#xff0c;那么则 R R R上的商域 K R K_{R} KR​定义为 K R { a b ∣ a , b ∈ R , b ≠ 0 } K_{R} \left\{ \frac{a}{b}|a,b \in R,b \neq 0 \right\} KR​{ba​∣a,b∈R,b0} 其中 a b a ′ b ′ ∈ K R ⇔ a b ′ a ′ b ∈ R \frac…

MYSQL 三、mysql基础知识 4(存储过程与函数)

MySQL从5.0版本开始支持存储过程和函数。存储过程和函数能够将复杂的SQL逻辑封装在一起&#xff0c;应用程序无须关注存储过程和函数内部复杂的SQL逻辑&#xff0c;而只需要简单地调用存储过程和函数即可。 一、存储过程概述&#xff1a; 1.1理解&#xff1a; 含义&am…

vue项目导入 .xlsx 文件

直接上代码&#xff0c;简单示例&#xff1a; 点击导入按钮&#xff0c;弹出导入弹窗&#xff1b; template 部分的代码&#xff1a; <div><el-buttonclass"filter-item"style"margin-left: 10px; margin-bottom: 20px; height: 30px"type"…

ARM-V9 RME(Realm Management Extension)系统架构之功耗管理

安全之安全(security)博客目录导读 目录 一、系统功耗管理 1、功耗状态 2、PE功耗管理 3、系统和PE集群功耗管理 4、系统功耗状态 二、RME组件功耗管理 本节规定了RME系统的功耗管理规则。 功耗管理流程定义了系统及其组件如何在各种电源状态之间进行转换&#xff0c;以…

深度学习中的神经网络——揭秘人工智能的核心技术

在当今科技领域&#xff0c;人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;无疑是最热门的话题之一。而作为人工智能领域的核心技术&#xff0c;神经网络&#xff08;Neural Networks&#xff09;正逐渐改变着我们的生活&#xff0c;并在诸如图像…

论文研读|以真实图像为参考依据的AIGC检测

前言&#xff1a;这篇文章介绍几篇AIGC检测的相关工作&#xff0c;其中前几篇文章是以真实图像的特征作为标准进行检测&#xff0c;最后一篇文章就当拓展一下知识边界吧&#xff5e; 目录 Detecting Generated Images by Real Images Only (202311 arXiv)Let Real Images be as…

深入解析Web通信 HTTP、HTTPS 和 WebSocket

在现代Web开发中,了解和掌握HTTP、HTTPS以及WebSocket协议是非常重要的。这些协议是实现Web应用程序之间通信的基石。本文将详细介绍这三种协议,包括它们的基本概念、工作原理、优缺点以及适用场景。通过深入解析它们的特点和应用,帮助读者更好地理解和使用这些协议。 一、…

【Chrome插件】如何在Chrome插件开发中处理复杂数据结构的存储

最近俺在接触 Chrome 插件开发&#xff0c;需要把一个数据存放到浏览器的存储中。这个数据结构有点复杂&#xff0c;它包含一个 Map 和一个数组。我使用 chrome.storage.local API来存储这个数据&#xff0c;然后在另一个地方获取数据。保存数据的代码并没有报错&#xff0c;但…

代码随想录算法训练营第37天|● 56.合并区间● 738.单调递增的数字

合并区间 56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 按照左边界从小到大排序之后&#xff0c;如果 intervals[i][0] < intervals[i - 1][1] 即intervals[i]的左边界 < intervals[i - 1]的右边界&#xff0c;则一定有重叠。&#xff08;本题相邻区间也算重贴…

SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件

SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件 H2 是一个用 Java 开发的嵌入式数据库&#xff0c;它的主要特性使其成为嵌入式应用程序的理想选择。H2 仅是一个类库&#xff0c;可以直接嵌入到应用项目中&#xff0c;而无需独立安装客户端和服务器端。 常用开源数…

网页自动化工具入门篇之常用自动化工具

1. Selenium 优点: 功能强大&#xff0c;可以与几乎所有的现代浏览器配合使用。支持多种编程语言&#xff08;如Python, Java, C#, Ruby等&#xff09;。能够处理复杂的网页交互&#xff0c;包括按钮点击、表单填写、拖拽操作等。 缺点: 相对较慢&#xff0c;因为它是真正启动…