Go中的context 包使用详解

news2025/1/9 11:01:41

context 包在 Go 中非常重要,特别是在处理并发和超时的场景下,它能让你在多个 goroutine 之间传递取消信号、超时控制或其他控制信息。context 是 Go 并发模型中的一个重要工具,尤其适用于 HTTP 请求、数据库操作、分布式系统等场景。

1. 基本概念

context 包的主要功能是提供一个 Context 类型,允许在多个 goroutine 之间共享请求范围的信息,并在需要时提供取消信号。

Context 是不可变的,一旦创建就不能修改。每次操作都返回一个新的 Context 对象。

2. 常见用法

  • 传递取消信号:在多个 goroutine 之间传递取消信号。
  • 设置超时:为操作设置超时限制。
  • 传递请求范围的值:可以在上下文中传递请求的元数据(如用户 ID、请求 ID)。

3. context 包的基本结构

context 包提供了几种不同类型的 Context,最常用的包括:

  • context.Background():根上下文,通常用于程序的顶层。
  • context.TODO():用于暂时没有明确上下文的地方,表示一个不确定的上下文。
  • context.WithCancel():创建一个可取消的上下文。
  • context.WithTimeout():创建一个带有超时的上下文。
  • context.WithDeadline():创建一个带有具体截止时间的上下文。
  • context.WithValue():创建一个可以存储值的上下文。

4. context.Background()context.TODO()

  • context.Background() 通常用于程序的顶层调用,表示一个没有附加元数据的空上下文。它通常作为其他上下文的根基。
  • context.TODO() 用于你不确定当前使用哪种上下文的地方,表示暂时还没有决定。
ctx := context.Background()  // 用作根上下文
// 或者
ctx := context.TODO()  // 用作还未确定上下文的地方

5. context.WithCancel()

context.WithCancel() 创建一个可以手动取消的上下文。当你取消这个上下文时,所有基于该上下文的 goroutine 都会收到取消信号。

package main

import (
	"context"
	"fmt"
	"time"
)

func doWork(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("Work cancelled:", ctx.Err())
			return
		default:
			// 模拟一些工作
			fmt.Println("Working...")
			time.Sleep(1 * time.Second)
		}
	}
}

func main() {
	// 创建一个可取消的上下文
	ctx, cancel := context.WithCancel(context.Background())

	// 启动一个 goroutine 执行任务
	go doWork(ctx)

	// 模拟执行一段时间后取消
	time.Sleep(3 * time.Second)
	cancel()  // 取消上下文,通知 goroutine 停止工作

	// 等待 goroutine 完成
	time.Sleep(1 * time.Second)
}

输出:

Working...
Working...
Working...
Work cancelled: context canceled

在这个例子中,cancel() 触发了 ctx.Done() 的信号,通知 doWork 函数退出。

6. context.WithTimeout()context.WithDeadline()

context.WithTimeout() 创建一个具有超时限制的上下文,超时后自动取消。context.WithDeadline() 类似,但你指定的是一个具体的截止时间。

示例:使用 WithTimeout
package main

import (
	"context"
	"fmt"
	"time"
)

func doWork(ctx context.Context) {
	select {
	case <-time.After(2 * time.Second):  // 模拟耗时操作
		fmt.Println("Work completed")
	case <-ctx.Done():
		fmt.Println("Work cancelled:", ctx.Err())
	}
}

func main() {
	// 创建一个带有 1 秒超时的上下文
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	// 启动 goroutine 执行任务
	go doWork(ctx)

	// 等待 2 秒,超过了超时时间
	time.Sleep(2 * time.Second)
}

输出:

Work cancelled: context deadline exceeded

在这个例子中,由于上下文在 1 秒后超时,doWork 会在超时后取消任务。

示例:使用 WithDeadline
package main

import (
	"context"
	"fmt"
	"time"
)

func doWork(ctx context.Context) {
	select {
	case <-time.After(2 * time.Second):  // 模拟耗时操作
		fmt.Println("Work completed")
	case <-ctx.Done():
		fmt.Println("Work cancelled:", ctx.Err())
	}
}

func main() {
	// 创建一个截止时间为当前时间加 1 秒的上下文
	deadline := time.Now().Add(1 * time.Second)
	ctx, cancel := context.WithDeadline(context.Background(), deadline)
	defer cancel()

	// 启动 goroutine 执行任务
	go doWork(ctx)

	// 等待 2 秒,超出了截止时间
	time.Sleep(2 * time.Second)
}

输出:

Work cancelled: context deadline exceeded

7. context.WithValue()

context.WithValue() 允许你在上下文中存储键值对,以便在不同的 goroutine 之间共享数据。通常用于请求 ID 或其他元数据的传递。

package main

import (
	"context"
	"fmt"
)

type key string

func main() {
	// 创建一个上下文并在其中存储一个值
	ctx := context.WithValue(context.Background(), key("userID"), 42)

	// 从上下文中获取值
	userID := ctx.Value(key("userID"))
	fmt.Println("UserID:", userID)
}

输出:

UserID: 42

8. context 在并发中的典型应用场景

  • HTTP 请求处理:在 web 应用中,你通常会为每个请求创建一个 context,以便在请求生命周期内传递取消信号、超时、身份验证信息等。
  • 数据库操作:当进行数据库查询时,可以使用 context 来设置超时、取消信号等,确保操作不会因超时而挂起。
  • 分布式任务:在微服务架构中,context 可以在服务之间传递请求信息,并确保某个操作超时或取消时其他相关操作也会停止。

9. context 的使用注意事项

  • 不要将 context 存储在结构体或 global 变量中,因为 context 是短生命周期的,应该只在请求的生命周期内传递。
  • 不要将 context 用作存储实际的数据,它主要用于传递控制信号(如取消信号、超时等)。
  • 避免重复创建:在每次使用 context.WithXXX 时,应该返回一个新的 Context,并通过 defer cancel() 确保在操作完成后释放资源。

总结

  • context 是 Go 中非常重要的并发工具,适用于传递取消信号、超时控制和请求范围的数据。
  • 主要的创建函数包括 WithCancelWithTimeoutWithDeadlineWithValue,它们允许在不同的场景下创建上下文。
  • context 的传递机制让我们能够在多个 goroutine 之间共享控制信息,如取消信号、超时或元数据,避免了手动的锁机制,使并发编程更加简洁和高效。

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

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

相关文章

小程序租赁系统开发的优势与应用前景分析

内容概要 小程序租赁系统是一种新兴的数字化解决方案&#xff0c;旨在为用户提供更加便捷与高效的租赁服务。它通常包括一系列功能&#xff0c;如在线浏览、即时预定、支付功能以及用户反馈机制。这些系统在使用上极为友好&#xff0c;让用户能够轻松选择所需的商品或服务&…

25/1/8 算法笔记<强化学习> GYM环境

前几天花了好多时间在装各个仿真环境上&#xff0c;有V-rep,Pybullet,unity的Ml-agent,很多一大堆&#xff0c;好多好多问题差点逼疯我&#xff0c;可能就pybullet能玩一点&#xff0c;到之后学了机器人我再来玩它&#xff0c;最后的最后&#xff0c;我发现还得是我的gym&#…

学习随记:word2vec中归一化处理的作用

答案来自ai&#xff0c;直接复用为参考&#xff1a; 向量归一化的好处 将向量进行归一化&#xff0c;使其模长为 1&#xff08;即投射到单位圆/单位球上&#xff09;&#xff0c;在许多情况下具有实际意义和计算优势。以下是归一化的主要好处和原因&#xff1a; 1. 提高数值稳…

【C++】B2108 图像模糊处理

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述题目内容输入格式输出格式示例输入&#xff1a;输出&#xff1a; &#x1f4af;题目分析问题拆解 &#x1f4af;我的做法代码实现代码分析 &#x1f4af;老师的做法…

selenium+pyqt5自动化工具总结

说明&#xff1a;本工具是&#xff0c;操作外部google浏览器、selenium是无法操作qt界面中嵌套的浏览器的&#xff0c; 工具在后面 1. 代码结构 pycharm打开的文件下&#xff0c;再写一个子文件&#xff0c;文件导入的时候把子文件名带上 这样就可以在 外层使用命令 pyinst…

经典多模态模型CLIP - 直观且详尽的解释

对比语言-图像预训练&#xff08;CLIP&#xff09;&#xff0c;这是一种创新的多模态建模策略&#xff0c;能够创建视觉和语言的联合表示。CLIP 的效果非常出色&#xff0c;可以用于构建高度特定且性能卓越的分类器&#xff0c;而无需任何训练数据。本文将深入探讨其理论基础&a…

新时期下k8s 网络插件calico 安装

1、k8s master节点初始化完毕以后一直处于notreadey状态&#xff0c;一直怀疑是安装有问题或者是初始化有问题&#xff08;当然&#xff0c;如果真有问题要先解决这些问题&#xff09;&#xff0c;经过不断探索才发现是网络插件没有安装导致的&#xff0c;根据建议安装calico插…

【图像加密解密】Logistic混沌映射的彩色图像加密算法复现(含相关性检验)【Matlab完整源码 1期】

1、说明 本文给出详细完整代码、完整的实验报告和PPT。 环境&#xff1a;MATLAB2019a 复现文献&#xff1a;[1]黄硕.基于改进的Logistic混沌映射彩色图像加密算法[J].河南工程学院学报(自然科学版),2015,27(02):63-67. 主要目的是为了快速了解何为混沌序列、混沌序列产生、…

[AUTOSAR 基础入门] - RTE虚拟总线详解

文章目录 一、什么是RTE二、RTE的作用三、RTE对Runnables的运行支撑四、RTE与通信4.1. RTE – ECU之间通信4.2. RTE - Sender/Receiver 通信4.2.1 不使用队列&#xff08;直接访问&#xff09;4.2.2 不使用队列&#xff08;缓存访问&#xff09;4.2.3 使用队列 4.3 RTE - Clien…

Linux下文件操作相关接口

文章目录 一 文件是什么普通数据文件 二 文件是谁打开的进程用户 三 进程打开文件的相关的接口c语言标准库相关文件接口1. fopen 函数2. fread 函数3. fwrite 函数4. fclose 函数5. fseek 函数 linux系统调用接口1. open 系统调用2. creat 系统调用3. read 系统调用4. write 系…

用Python实现简单的任务自动化

目录 1. 自动发送邮件提醒 2. 自动备份文件 3. 自动下载网页内容 总结 在现代工作和生活中,任务自动化可以极大地提高效率和准确性。Python,作为一种功能强大且易于学习的编程语言,是实现任务自动化的理想选择。本文将通过几个简单而实用的案例,展示如何用Python实现任…

小程序开发-页面事件之上拉触底实战案例

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

Docker 服务、镜像、容器之命令(Docker Services, Images, and Container Commands)

Docker 服务、镜像、容器之命令 Docker是一个强大的容器化平台&#xff0c;能够帮助开发者高效地构建、部署和管理应用程序。本文将详细介绍Docker的服务命令、镜像命令和容器命令&#xff0c;帮助你快速上手Docker。 一、Docker的服务相关命令 在使用Docker之前&#xff0c…

STM32内置Flash

一、原理 利用flash存储用户数据需要注意查看&#xff0c;用户数据是否会覆盖芯片运行程序。 IAP&#xff08;在程序中编程&#xff09;利用程序修改程序本身&#xff0c;和OTA是一个原理。IAP在程序中编程支持任意一种通信下载。 ICP&#xff08;在电路中编程&#xff0c;通…

两种方式实现Kepware与PLC之间的心跳检测

两种方式实现Kepware与PLC之间的心跳检测 实现Kepware与PLC之间的心跳检测1.OPCUA 外挂程序2.Kepware Advanced Tag 实现Kepware与PLC之间的心跳检测 1.OPCUA 外挂程序 这是通过上位程序来触发心跳的一种机制&#xff0c;在C#中&#xff0c;可以利用OPC UAOPCAutodll的方式…

英伟达Project Digits赋能医疗大模型:创新应用与未来展望

英伟达Project Digits赋能医疗大模型&#xff1a;创新应用与未来展望 一、引言 1.1 研究背景与意义 在当今数字化时代&#xff0c;医疗行业作为关乎国计民生的关键领域&#xff0c;正面临着前所未有的挑战与机遇。一方面&#xff0c;传统医疗模式在应对海量医疗数据的处理、复…

中国省级产业结构高级化及合理化数据测算(2000-2023年)

一、数据介绍 数据名称&#xff1a;中国省级产业结构高级化、泰尔指数 数据年份&#xff1a;2000-2023年 数据范围&#xff1a;31个省份 数据来源&#xff1a;中国统计年鉴、国家统计局 数据整理&#xff1a;内含原始版本、线性插值版本、ARIMA填补版本 数据说明&#xf…

关于Mac使用VSCode连接虚拟机

1. 下载插件 输入Remote - SSH下载下图两个插件。 2. 配置虚拟机信息 按图示步骤点击完成后&#xff0c;进入到虚拟主机的配置页面。 其中Host可以自定义主机名&#xff0c;HostName是虚拟机ip&#xff0c;可以通过ifconfig eth0查看ip&#xff0c;User是虚拟机的用户名。…

GOGOGO 接口

低高耦合?【程序中追求低耦合,所以接口广用】 低耦合:关联依赖性弱(你走了我还在) 高耦合:关联依赖性强(牵一发而动全身) 接口 概念:多个抽象方法的集合,只有结构无具体实现,并交给实现类完成功能操作【接口写功能,实现类写具体实现】 语法结构: 定义接口的关…

nginx反向代理+缓存

1、nginx-LB配置页面缓存 [rootOldboy conf]# vi nginx.conf http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;include proxy.conf; …