当前位置: 首页 > news >正文

Go 里的超时控制

前言

日常开发中我们大概率会遇到超时控制的场景,比如一个批量耗时任务、网络请求等;一个良好的超时控制可以有效的避免一些问题(比如 goroutine 泄露、资源不释放等)。

Timer

在 go 中实现超时控制的方法非常简单,首先第一种方案是 Time.After(d Duration):

func main() {fmt.Println(time.Now())x := <-time.After(3 * time.Second)fmt.Println(x)
}

output:

2021-10-27 23:06:04.304596 +0800 CST m=+0.000085653
2021-10-27 23:06:07.306311 +0800 CST m=+3.001711390

在这里插入图片描述
time.After() 会返回一个 Channel,该 Channel 会在延时 d 段时间后写入数据。

有了这个特性就可以实现一些异步控制超时的场景:

func main() {ch := make(chan struct{}, 1)go func() {fmt.Println("do something...")time.Sleep(4*time.Second)ch<- struct{}{}}()select {case <-ch:fmt.Println("done")case <-time.After(3*time.Second):fmt.Println("timeout")}
}

这里假设有一个 goroutine 在跑一个耗时任务,利用 select 有一个 channel 获取到数据便退出的特性,当 goroutine 没有在有限时间内完成任务时,主 goroutine 便会退出,也就达到了超时的目的。

output:

do something...
timeout

timer.After 取消,同时 Channel 发出消息,也可以关闭通道等通知方式。

注意 Channel 最好是有大小,防止阻塞 goroutine ,导致泄露。

Context

第二种方案是利用 context,go 的 context 功能强大;
在这里插入图片描述
利用 context.WithTimeout() 方法会返回一个具有超时功能的上下文。

	ch := make(chan string)timeout, cancel := context.WithTimeout(context.Background(), 3*time.Second)defer cancel()go func() {time.Sleep(time.Second * 4)ch <- "done"}()select {case res := <-ch:fmt.Println(res)case <-timeout.Done():fmt.Println("timout", timeout.Err())}

同样的用法,context 的 Done() 函数会返回一个 channel,该 channel 会在当前工作完成或者是上下文取消生效。

timout context deadline exceeded

通过 timeout.Err() 也能知道当前 context 关闭的原因。

goroutine 传递 context

使用 context 还有一个好处是,可以利用其天然在多个 goroutine 中传递的特性,让所有传递了该 context 的 goroutine 同时接收到取消通知,这点在多 go 中应用非常广泛。

func main() {total := 12var num int32log.Println("begin")ctx, cancelFunc := context.WithTimeout(context.Background(), 3*time.Second)for i := 0; i < total; i++ {go func() {//time.Sleep(3 * time.Second)atomic.AddInt32(&num, 1)if atomic.LoadInt32(&num) == 10 {cancelFunc()}}()}for i := 0; i < 5; i++ {go func() {select {case <-ctx.Done():log.Println("ctx1 done", ctx.Err())}for i := 0; i < 2; i++ {go func() {select {case <-ctx.Done():log.Println("ctx2 done", ctx.Err())}}()}}()}time.Sleep(time.Second*5)log.Println("end", ctx.Err())fmt.Printf("执行完毕 %v", num)
}

在以上例子中,无论 goroutine 嵌套了多少层,都是可以在 context 取消时获得消息(当然前提是 context 得传递走)

某些特殊情况需要提前取消 context 时,也可以手动调用 cancelFunc() 函数。

Gin 中的案例

Gin 提供的 Shutdown(ctx) 函数也充分使用了 context。

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()if err := srv.Shutdown(ctx); err != nil {log.Fatal("Server Shutdown:", err)}log.Println("Server exiting")

在这里插入图片描述

比如以上代码便是超时等待 10s 进行 Gin 的资源释放,实现的原理也和上文的例子相同。

相关文章:

Go 里的超时控制

前言 日常开发中我们大概率会遇到超时控制的场景&#xff0c;比如一个批量耗时任务、网络请求等&#xff1b;一个良好的超时控制可以有效的避免一些问题&#xff08;比如 goroutine 泄露、资源不释放等&#xff09;。 Timer 在 go 中实现超时控制的方法非常简单&#xff0c;…...

一文彻底搞清楚Spark Schema

前言 Spark Schema定义了DataFrame的结构,可以通过对DataFrame对象调用printSchema()方法来获得该结构。Spark SQL提供了StructType和StructField类以编程方式指定架构。 默认情况下,Spark从数据中推断schema,但有时我们可能需要定义自己的schema(列名和数据类型),尤其…...

Nginx多出口IP解决代理端口数量限制,CentOS安装Nginx并开启https2.0

Nginx多出口IP解决代理端口数量限制,CentOS安装Nginx并开启https2.0。 配置文件如下: http {...upstream test {server www.test.com;}server {listen 80 default_server;server_name _;location / {proxy_pass http://test;proxy_bind $split_ip...

SpringBoot项目(百度AI整合)——如何在Springboot中使用语音文件识别 ffmpeg的安装和使用

前言 前言&#xff1a;在实际使用中&#xff0c;经常要参考官方的案例&#xff0c;但有时候因为工具的不一样&#xff0c;比如idea 和 eclipse&#xff0c;普通项目和spring项目等的差别&#xff1b;还有时候因为水平有限&#xff0c;难以在散布于官方的各个文档读懂&#xff…...

探索古彝文AI识别技术:助力中国传统文化的传承与发扬

目录 ⭐️ 写在前面 ⭐️ 一、什么是古彝文 1.1 古彝文介绍 1.2 古彝文与其他古文字示例 1.3 古彝文的重要性 ⭐️二、AI识别技术的挑战与前景 2.1 挑战 2.2 前景 ⭐️三、合合信息AI识别技术 3.1 智能文字识别技术&#x1f44d;&#x1f44d; 3.2 古文识别应用 ⭐…...

mysql面试题2:说一说MySQL的架构设计?一条 MySQL 语句执行的步骤?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说MySQL的架构设计? MySQL的架构设计主要包括以下几个组件: 连接器(Connector):负责与客户端建立连接,并进行身份验证和授权。 查询缓存…...

UPnP协议和SSDP协议

1、两种协议 UPnP协议&#xff1a;Universal Plug and Play&#xff0c;广义的即插即用。UPnP协议的目的&#xff1a;当有新设备连接上网络&#xff0c;网络上的其他设备能够马上知道有新设备加入&#xff0c;然后这些设备能互相宣传和发现彼此&#xff0c;以便能使用和控制彼…...

notepad++配置python2环境

&#xff08;1&#xff09;python2版本下载&#xff1a;Index of /ftp/python/2.7.8/https://www.python.org/ftp/python/2.7.8/ &#xff08;2&#xff09; 配置notepad环境 1.打开Notepad&#xff0c;点击“插件”-“插件管理器”&#xff0c;在“可用”选项卡中&#xff0c…...

在ThinkAdmin中弹出层关闭后回调

在thinkadmin里面&#xff0c;窗口的的一些方法全部都集成在admin.js里面&#xff0c;在之前的文章中也有出现过类似的问题&#xff0c;就是对动态加载的数据进行统计&#xff0c;那时候写也是想记录下&#xff0c;现在自己都不记得是哪个站用的了&#xff0c;所以在这里也把这…...

vue3 和vue2 的比较

文章目录 生命周期多根节点Composition API组合式APIOptions API与composition API对比优化逻辑组织优化逻辑复用 异步组件(Suspense)Suspense组件 响应式原理性能体积优化编译优化diff算法优化静态提升数据劫持&#xff08;响应式系统&#xff09;优化 生命周期 vue3在组合AP…...

算法通过村第八关-树(深度优先)黄金笔记|寻找祖先

文章目录 前言最近公共祖先问题总结 前言 提示&#xff1a;生活就是一场有很多规则&#xff0c;却没有裁判的比赛。 --约瑟夫布罗茨基《悲伤与理智》 最近公共祖先问题 参考题目地址&#xff1a;236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 如果将搜索…...

postgresql|数据库|数据库测试工具pgbench之使用

前言&#xff1a; 数据库是项目中的重要组件&#xff0c;也是一个基础的重要组件&#xff0c;其地位说是第一我想应该是没有什么太多问题的。 那么&#xff0c;数据库的设计这些方面是不用多说的&#xff0c;关键的第一步&#xff0c;主要是涉及数据库的部署方式&#xff0c;…...

代码随想录Day51 | 309.最佳买卖股票时机含冷冻期

309. 买卖股票的最佳时机含冷冻期 class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();if (n 0) return 0;vector<vector<int>> dp(n, vector<int>(4, 0));dp[0][0] - prices[0]; // 持股票for (int i 1; i &l…...

libopenssl 实现私钥加密公钥解密

在需要验证可信来源时&#xff0c;需要用到签名验签。因此&#xff0c;需要使用私钥加密&#xff0c;公钥解密&#xff0c;取得被加密的信息。这就会使用到私钥加密&#xff0c;公钥解密的场景了。 参考&#xff1a; https://github.com/openssl/openssl/issues/20493 https:/…...

代码随想录 Day - 51|#309 最佳买卖股票时机含冷冻期|#714 买卖股票的最佳时机含手续费

清单 ● 309.最佳买卖股票时机含冷冻期 ● 714.买卖股票的最佳时机含手续费 LeetCode #309 最佳买卖股票时机含冷冻期 1. 题目 给定一个整数数组&#xff0c;其中第 i 个元素代表了第 i 天的股票价格 。 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可…...

.net 使用IL生成代理类实现AOP对比Java Spring Boot的AOP

首先&#xff0c;我们需要定义一个接口&#xff0c;代表我们要代理的目标对象的功能&#xff1a; // 日志记录器接口 public interface ILogger {/// <summary>/// 记录日志/// </summary>/// <param name"message">日志消息</param>void L…...

美容店预约小程序搭建流程

随着科技的不断发展&#xff0c;小程序已经成为了人们生活中不可或缺的一部分。对于美容店来说&#xff0c;搭建一个预约小程序不仅可以提高工作效率&#xff0c;还可以增加客户数量、提高服务质量。那么&#xff0c;如何搭建一个美容店预约小程序呢&#xff1f;本文将为你详细…...

ppt 作图 如何生成eps格式

需求 ppt中画的图&#xff0c;按照eps格式导出。 环境 软件: ppt, Gsview(用来将ps格式转成eps), Adobe 操作系统&#xff1a; win11 思路 直接在ppt里选择adobe打印机&#xff0c;将图片以文件形式打印到ps格式的文件中&#xff0c;再由gsview转化成eps。 建议在本身就…...

渗透测试中的前端调试(上)

一、前言 前端调试是安全测试的重要组成部分。它能够帮助我们掌握网页的运行原理&#xff0c;包括js脚本的逻辑、加解密的方法、网络请求的参数等。利用这些信息&#xff0c;我们就可以更准确地发现网站的漏洞&#xff0c;制定出有效的攻击策略。前端知识对于安全来说&#xff…...

跨境电商引流之Reddit营销,入门保姆级攻略

在当今竞争激烈的在线市场中&#xff0c;企业不断寻求新的方法来加强其数字营销工作。Reddit 是最受欢迎的社交媒体平台之一&#xff0c;为企业提供了巨大的潜力&#xff0c;可以通过引人入胜且相关的内容来接触目标受众。然而&#xff0c;将 Reddit 用于营销目的需要仔细考虑某…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...