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

golang中的上下文

背景

在Go语言中,使用context包来管理跨API和进程间的请求生命周期是常见的做法。特别是在涉及到并发编程时,如启动协程(goroutine)来处理异步任务,正确地传递和监听context变得尤为重要。比如,在gin框架中,发起一个http请求,把context传递到协程中,当http请求结束时就会执行上下文取消逻辑,从而导致异步协程退出。

我们通过一个示例模拟在gin框架(或任何类似的Web框架)中可能遇到的一个问题:在HTTP请求处理过程中启动协程,并传递context以控制协程的生命周期。

package mainimport ("context""fmt""time"
)func main() {// 创建一个带取消功能的上下文ctx, cancel := context.WithCancel(context.Background())// 启动一个协程go func(ctx context.Context) {ticker := time.NewTicker(1 * time.Second)defer ticker.Stop() // 确保ticker在退出时停止for {select {case <-ticker.C:fmt.Println("协程正在运行...")case <-ctx.Done():fmt.Println("协程收到取消信号,退出执行")return}}}(ctx)// 主程序等待3秒后取消上下文time.Sleep(3 * time.Second)cancel()time.Sleep(1 * time.Second)fmt.Println("主程序结束")
}

当我们执行取消操作,异步协程监听到Done信号,执行了退出协程的逻辑。 

但是,在某些情况下,比如,上述提到的http请求这样的情况下,我们并不期望context取消,导致异步协程退出执行。

那我们应该怎么办呢?

很容易想到的是new一个新的context使其继承父context。但是,这里就会遇到一个问题,简单的拷贝父context是不行的,比如,下面这种写法,当父ctx取消了,newCtx也会取消。

ctx, cancel := context.WithCancel(context.Background())newCtx, _ := context.WithTimeout(ctx, 3*time.Second)

那么要怎么办呢?context包中有一个方法:WithoutCancel,这个方法只拷贝了父ctx的Value,没有继承父ctx的Done通道。

案例

我们提供一个简单的案例,模拟在协程中处理逻辑。

package mainimport ("context""fmt""time"
)func main() {// 创建一个带取消功能的上下文ctx, cancel := context.WithCancel(context.Background())ctx = context.WithValue(ctx, "traceId", "123456")ctx = context.WithValue(ctx, "userId", "u123")newCtx := context.WithoutCancel(ctx)// 启动一个协程go func(ctx context.Context) {ticker := time.NewTicker(1 * time.Second)defer ticker.Stop() // 确保ticker在退出时停止for {select {case <-ticker.C:fmt.Println("traceId:", ctx.Value("traceId"))fmt.Println("userId:", ctx.Value("userId"))fmt.Println("协程正在运行...")case <-ctx.Done():fmt.Println("协程收到取消信号,退出执行")return}}}(newCtx)// 主程序等待3秒后取消上下文time.Sleep(3 * time.Second)cancel()<-newCtx.Done()// 这种情况下,不会收到取消信号,父上下文的取消信号不会传递给子上下文// 给协程一些时间进行清理和输出time.Sleep(1 * time.Second)fmt.Println("主程序结束")
}

在Go语言的context包中,WithoutCancel函数提供了一种创建新上下文的方法,这个新上下文不会继承其父上下文的取消逻辑。这意味着,当父上下文被取消时,由WithoutCancel返回的上下文并不会被自动取消。

// WithoutCancel 返回一个父上下文的副本,该副本在父上下文被取消时不会被取消。  
// 返回的上下文没有截止时间或错误,并且其 Done 通道为 nil。  
// 对返回的上下文调用 [Cause] 方法会返回 nil。  
func WithoutCancel(parent Context) Context {if parent == nil {panic("cannot create context from nil parent")}return withoutCancelCtx{parent}
}type withoutCancelCtx struct {c Context
}// withoutCancelCtx 类型的 Done 方法被重写,返回 nil 通道。  
func (w withoutCancelCtx) Done() <-chan struct{} {  return nil // 返回空的 Done 通道,表示这个上下文不会被取消  
}

WithoutCancel函数接受一个父上下文作为参数,并返回一个新的上下文。这个新上下文是一个withoutCancelCtx类型的实例,它内部包含了父上下文,但重写了Done方法。

由于withoutCancelCtx重写了Done方法并返回nil,这意味着当你监听这个上下文的Done通道时,它永远不会关闭,因此你的协程或任务将不会因为父上下文的取消而退出。这对于需要确保某些任务在父上下文取消后仍然继续运行的场景非常有用。

相关文章:

golang中的上下文

背景 在Go语言中&#xff0c;使用context包来管理跨API和进程间的请求生命周期是常见的做法。特别是在涉及到并发编程时&#xff0c;如启动协程&#xff08;goroutine&#xff09;来处理异步任务&#xff0c;正确地传递和监听context变得尤为重要。比如&#xff0c;在gin框架中…...

Navigation2 算法流程

转自 https://zhuanlan.zhihu.com/p/405670882 此文仅作学习笔记 启动流程 在仿真环境中启动导航包的示例程序&#xff0c;执行nav2_bringup/bringup/launch/tb3_simulation_launch.py文件。ROS2的launch文件支持采用python语言来编写以支持更加复杂的功能&#xff0c;本文件…...

OpenAI swarm+ Ollama快速构建本地多智能体服务 - 1. 服务构建教程

OpenAI开源了多智能体编排的工程swarm&#xff0c;今天介绍一下swarm与OLLAMA如何结合使用的教程&#xff0c;在本地构建自己的多智能体服务&#xff0c;并给大家实践演示几个案例。 安装步骤 安装ollama&#xff0c;在官网下载对应操作系统的版本即可&#xff0c;下载后用ol…...

HTB:Wifinetic[WriteUP]

目录 连接至HTB并启动靶机 1.What is the name of the OpenWRT backup file accessible over FTP? 使用nmap对靶机21、22端口进行脚本、服务信息扫描 2.Whats the WiFi password for SSID OpenWRT? 3.Which user reused the WiFi password on thier local account? 4.…...

专业学习|马尔可夫链(概念、变体以及例题)

一、马尔可夫链的概念及组成 &#xff08;一&#xff09;学习资料分享 来源&#xff1a;024-一张图&#xff0c;但讲懂马尔可夫决策过程_哔哩哔哩_bilibili 马尔可夫链提供了一种建模随机过程的方法&#xff0c;具有广泛的应用。在实际问题中&#xff0c;通过转移概率矩阵及初…...

RK3576 安卓SDK编译环境搭建

编译 Android14 对机器的配置要求较高: 建议预留500G存储 多分配CPU和内存 建议使用 Ubuntu 20.04 操作系统或更高版本 sudo apt-get updatesudo apt-get install make gcc sudo apt-get install g++ patchelf gawk texinfo chrpath diffstat binfmt-support sudo apt-get …...

Renesas R7FA8D1BH (Cortex®-M85) 上光电编码器测速功能

目录 概述 1 软硬件 1.1 软硬件环境信息 1.2 开发板信息 1.3 调试器信息 2 硬件架构 2.1 硬件框架结构 2.2 测速功能原理介绍 2.2.1 理论描述 2.2.2 实现原理 2.2.3 系统硬件结构 3 软件实现 3.1 FSP配置项目 3.2 代码实现 3.2.1 初始化函数 3.2.2 功能函数 3.…...

软件测试学习笔记丨Linux三剑客-sed

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/32521 一、简介 sed&#xff08;Stream editor&#xff09;是一个功能强大的文本流编辑器&#xff0c;主要用于对文本进行处理和转换。它适用于自动化处理大量的文本数据&#xff0c;能够支持…...

Vue脚手架学习 vue脚手架配置代理、插槽、Vuex使用、路由、ElementUi插件库的使用

目录 1.vue脚手架配置代理 1.1 方法一 1.2 方法二 2.插槽 2.1 默认插槽 2.2 具名插槽 2.3 作用域插槽 3.Vuex 3.1 概念 3.2 何时使用&#xff1f; 3.3 搭建vuex环境 3.4 基本使用 3.5 getters的使用 3.6 四个map方法的使用 3.6.1 mapState方法 3.6.2 mapGetter…...

使用yml文件安装环境时,如何添加conda和pip的镜像源

博客参考 添加conda镜像源 name: NAME channels:- conda-forge- pytorch- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2- defaults depende…...

c语言经典100例

1.字符串转为数字 #include <stdio.h>int strToInt(char *s) {int num0;int sign1;int step1;if (*s -){sign -1;s;}while (*s > 0&&*s < 9){num num*10(*s-0);step 10;s;}return num*sign; }int main() {char a[10] "-1234";char *s a ;pr…...

百易云资产管理运营系统 ufile.api.php SQL注入漏洞复现

0x01 产品描述&#xff1a; 百易云资产管理运营系统&#xff0c;是专门针对企业不动产资产管理和运营需求而设计的一套综合解决方案。该系统能够覆盖资产的全生命周期管理&#xff0c;包括资产的登记、盘点、评估、处置等多个环节&#xff0c;同时提供强大的运营分析功能&#…...

【分布式微服务云原生】《Redis RedLock 算法全解析:应对时钟漂移与网络分区挑战》

《Redis RedLock 算法全解析&#xff1a;应对时钟漂移与网络分区挑战》 摘要&#xff1a; 本文深入探讨 Redis 的 RedLock 算法&#xff0c;详细阐述其步骤及工作原理&#xff0c;同时重点分析该算法如何处理时钟漂移和网络分区这两个常见的分布式系统问题。读者将通过本文深入…...

OceanBase 的写盘与传统数据库有什么不同?

背景 在数据库开发过程中&#xff0c;“写盘”是一项核心操作&#xff0c;即将内存中暂存的数据安全地转储到磁盘上。在诸如MySQL这样的传统数据库管理系统中&#xff0c;写盘主要有以下几步&#xff1a;首先将数据写入缓存池&#xff1b;其次&#xff0c;为了确保数据的完整性…...

用Java爬虫API,轻松获取taobao商品SKU信息

在电子商务的世界里&#xff0c;SKU&#xff08;Stock Keeping Unit&#xff0c;库存单位&#xff09;是商品管理的基础。对于商家来说&#xff0c;SKU的详细信息对于库存管理、价格策略制定、市场分析等都有着重要作用。taobao作为中国最大的电子商务平台之一&#xff0c;提供…...

OpenHarmony 入门——ArkUI 自定义组件内同步的装饰器@State小结(二)

文章大纲 引言一、组件内状态装饰器State1、初始化2、使用规则3、变量的传递/访问规则说明4、支持的观察变化的场景5、State 变量的值初始化和更新机制6、State支持联合类型实例 引言 前一篇文章OpenHarmony 入门——ArkUI 自定义组件之间的状态装饰器小结&#xff08;一&…...

【Linux驱动开发】嵌入式Linux驱动开发基本步骤,字符设备开发入门,点亮LED

【Linux驱动开发】嵌入式Linux驱动开发基本步骤&#xff0c;字符设备开发入门&#xff0c;点亮LED 文章目录 开发环境驱动文件编译驱动安装驱动自动创建设备节点文件 驱动开发驱动设备号地址映射&#xff0c;虚拟内存和硬件内存地址字符驱动旧字符驱动新字符驱动 应用程序开发…...

搬砖14、Python网络编程入门

网络编程入门 计算机网络基础 计算机网络是独立自主的计算机互联而成的系统的总称&#xff0c;组建计算机网络最主要的目的是实现多台计算机之间的通信和资源共享。今天计算机网络中的设备和计算机网络的用户已经多得不可计数&#xff0c;而计算机网络也可以称得上是一个“复…...

Transformer: Attention is All you need

Transformer Transformer是基于Encoder-Decoder结构的&#xff0c;将Seq2Seq中的RNN/GRU部分更换为Self-Attention部分 位置编码 Positional Encoding Self-attention丢失了位置信息 CNN 卷积神经网络可以保存相邻的位置信息 RNN 是顺序输入的&#xff0c;是包含了位置信息…...

C++:排序算法

目录 一、插入排序 1.直接插入排序 2.希尔排序 二、交换排序 1.冒泡排序 2.快速排序 三、选择排序 1.简单选择排序 2.堆排序 四、归并排序 1.二路归并排序的递归实现 2.二路归并排序的非递归实现 一、插入排序 1.直接插入排序 直接插入排序的基本思想是&#xff…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...