Go 上下文 context.Context

Go语言中的上下文(Context)是一种用于在 Goroutines 之间传递取消信号、截止时间和其他请求范围值的标准方式。context 包提供了 Context 类型和一些相关的函数,用于在并发程序中有效地传递上下文信息。

在Go语言中,上下文通常用于以下场景:

  1. 请求的传递:当一个请求从客户端发送到服务器时,可以使用上下文来携带与该请求相关的数据。这些数据可以是用户的身份信息、请求的元数据或其他与请求相关的信息。通过将上下文传递给处理该请求的goroutine,可以确保在整个处理过程中访问这些数据。
  2. 取消操作:上下文可以用于取消正在进行的操作。当用户或其他代码发送取消信号时,可以将该信号传递给正在执行操作的goroutine。goroutine在接收到取消信号后,可以根据需要执行清理操作并退出。
  3. 截止时间:有时候需要在一段时间后终止正在进行的操作。通过将截止时间与上下文一起传递给goroutine,可以确保在超过截止时间后执行适当的清理操作并退出。
  4. 跨多个服务通信:当在分布式系统中使用Go语言时,上下文可以用于跨不同的服务之间传递请求数据、取消信号和截止时间。通过使用上下文,可以确保在整个系统中的各个服务之间保持一致的上下文和请求生命周期管理。

通过使用上下文,可以有效地在 Goroutines 之间传递取消信号、截止时间和请求范围的值,从而更好地控制并发程序的行为。

1. context.Context 接口

Context 接口定义了在 Goroutines 之间传递的上下文的基本方法:

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key interface{}) interface{}
}
  • Deadline():返回上下文的截止时间。如果存在截止时间,ok 为 true,否则为 false
  • Done():返回一个通道,该通道关闭时表示上下文被取消或者超过了截止时间。
  • Err():返回上下文取消的原因。如果上下文没有被取消,则返回 nil
  • Value(key):返回与给定 key 关联的值。这允许在上下文中传递请求范围的数据。

2. 创建上下文

在 Go 中,上下文可以通过 context.Background() 创建,它是一个无值的上下文,通常用作根上下文。根上下文不能被取消,也不能传递截止时间。

ctx := context.Background()

可以使用 context.WithCancelcontext.WithTimeoutcontext.WithDeadline 和 context.WithValue 等函数创建派生上下文,这些函数分别用于创建带有取消、超时、截止时间和值的上下文。

// 创建一个带有取消功能的上下文
ctx, cancel := context.WithCancel(context.Background())
 
// 创建一个带有超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 
// 创建一个带有截止时间的上下文
deadline := time.Now().Add(2 * time.Second)
ctx, cancel := context.WithDeadline(context.Background(), deadline)
 
// 创建一个带有值的上下文
key := "key"
value := "value"
ctx := context.WithValue(context.Background(), key, value)

3. 传递上下文

在 Go 中,通过函数参数将上下文传递给调用的函数,从而使调用的函数能够感知上下文的取消或超时。例如:

func myFunction(ctx context.Context) {
    // 在这里使用 ctx 处理逻辑
    select {
    case <-ctx.Done():
        // 上下文被取消,执行清理工作
        fmt.Println("Context canceled")
        return
    default:
        // 继续正常的逻辑
        fmt.Println("Doing some work")
    }
}
 
func main() {
    // 创建带有取消功能的上下文
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
 
    // 启动 Goroutine,传递上下文
    go myFunction(ctx)
 
    // 主 Goroutine 执行一些工作
    time.Sleep(2 * time.Second)
}

4. 上下文的取消

调用 cancel() 函数会取消与上下文相关的 Goroutines。一旦上下文被取消,与之关联的所有 Goroutines 都会收到取消信号。

ctx, cancel := context.WithCancel(context.Background())
 
// 启动 Goroutine,传递上下文
go func(ctx context.Context) {
    select {
    case <-ctx.Done():
        // 上下文被取消,执行清理工作
        fmt.Println("Context canceled")
        return
    }
}(ctx)
 
// 取消上下文
cancel()

5. 上下文的超时和截止时间

使用 context.WithTimeout 或 context.WithDeadline 函数可以设置上下文的超时或截止时间。当超过指定的时间后,上下文会自动取消。

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
 
// 启动 Goroutine,传递上下文
go func(ctx context.Context) {
    select {
    case <-ctx.Done():
        // 上下文超时,执行清理工作
        fmt.Println("Context timeout")
        return
    }
}(ctx)
 
// 主 Goroutine 执行一些工作
time.Sleep(3 * time.Second)

6. 上下文值

context.WithValue 函数可以用于在上下文中传递请求范围的值。这些值可以通过 context.Value 方法在上下文中检索。

ctx := context.WithValue(context.Background(), "user", "john_doe")
 
// 从上下文中获取值
value := ctx.Value("user")
fmt.Println(value) // 输出: john_doe

7. 上下文的链式调用

可以通过链式调用的方式,将多个上下文进行组合,形成一个父子关系的上下文链。

parentCtx := context.Background()
ctx1, cancel1 := context.WithTimeout(parentCtx, 2*time.Second)
defer cancel1()
 
ctx2, cancel2 := context.WithCancel(ctx1)
defer cancel2()

上述的 ctx2 是 ctx1 的子上下文,当 ctx1 超时或被取消时,ctx2 也会相应地被取消。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Minio - 多节点多驱动器安装部署

先决条件 网络互通 MinIO集群中的节点的网络需要互相双向互通。 MinIO API默认端口9000 MinIO console默认端口9001 MinIO强烈建议使用负载均衡器来管理与集群的连接。负载均衡器策略使用“最小连接数”逻辑&#xff0c;因为在部署中任何 MinIO 节点都可以接收、路由或处理…

什么是软件定制开发?|app网站小程序定制

什么是软件定制开发&#xff1f;|app网站小程序定制 软件定制开发是根据客户的特定需求&#xff0c;为其量身定制开发软件解决方案的全过程。与市面上已有的通用软件不同&#xff0c;软件定制开发可以满足客户在业务流程、功能要求、用户界面等方面的个性化需求。 软件定制开发…

Redis链表

前言 链表作为一种常见的数据结构&#xff0c;一般都会内置在很多高级语言中。由于Redis使用的是C语言并没有内置这种数据结构&#xff0c;所以Redis构建了自己的链表实现。 链表在Redis中应用广泛&#xff0c;比如列表建的底层实现之一就是链表。当一个列表键包含了数量比较多…

Python字符串类型

目录 目标 版本 官方文档 书写格式 字符串合并 常用函数 字母转小写&#xff08;首字母转大写&#xff09; 字母转小写&#xff08;适用于在国际化环境中&#xff0c;忽略字母大小写进行比较的场景&#xff09; 字母转小写&#xff08;适用于非国际化环境中&#xff0…

JSON 格式的接口测试流程【Eolink Apikit】

在进行JSON格式的接口测试时&#xff0c;需要使用工具发送HTTP请求并获取响应。测试工具可以是单独的测试框架&#xff0c;如 Eolink Apikit。测试人员需要根据接口文档和测试用例编写测试脚本&#xff0c;然后运行测试并分析结果&#xff0c;以确保接口的质量和稳定性。 当我…

数据库mysql详细教学

1024 byte 构成 1 kb 1024 KB > 1MB 1024 MB > 1GB 1024 GB > 1TB 1024 TB > 1PB 内存的数据&#xff0c;断电后会丢失。外存的数据&#xff0c;断电后数据还在~ “持久化” 这样的次&#xff0c;意思就是把数据写到硬盘上。 mysql的第一组基本操作&#xff1a;数…

02_SHELL编程之流程控制和循环语句

课程目标 熟悉流程控制语句基本语法&#xff0c;如if…else… 掌握for循环语句的基本语法结构 掌握while和until循环语句的基本语法结构 ###一、流程控制语句 ####1. 基本语法结构 F: false 假 T: true 真 if [ condition ];thencommandcommand fi ​ [ 条件 ] &&a…

吴恩达《机器学习》8-7:多元分类

在机器学习领域&#xff0c;经常会遇到不止两个类别的分类问题。这时&#xff0c;需要使用多类分类技术。本文将深入探讨多类分类&#xff0c;并结合学习内容中的示例&#xff0c;了解神经网络在解决这类问题时的应用。 一、理解多类分类 多类分类问题是指当目标有多个类别时…

获取微信小程序二维码

可直接通过微信扫描小程序二维码直接进入小程序&#xff0c;可用在分享推广业务。 目录 Curl请求方法 获取小程序token 获取小程序二维码 参数说明 注意 请求结果 Curl请求方法 需要请求微信小程序的API接口&#xff0c;封装好curl请求方法。 代码如下&#xff1a; /*…

LSB隐写+十六进制转字符串

这张图片同样使用的是LSB隐写&#xff08;即最不显著位隐写&#xff09; 但是这道题目使用一个小技巧&#xff0c;将flag用十六进制的形式加了一层伪装 LSB隐写 通过StegSolve打开该图片&#xff0c;之后选择Analyse-》data extract来分析图片的LSB隐写 首先先点击选择LSB …

MIB 6.1810实验Xv6 and Unix utilities(3)pingpong

Mit6.S081-实验1-Xv6 and Unix utilities-pingpong问题_Isana_Yashiro的博客-CSDN博客 Write a user-level program that uses xv6 system calls to ping-pong a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to…

【精选】JavaScript语法大合集【附代码和超详细介绍以及使用】

JavaScript语法大合集 JavaScript引入到文件 嵌入到HTML文件中 <body><script>var num10;console.log(num);</script> </body>引入本地独立JS文件 <body><script src"./hello.js"></script> </body>引入网络来源…

nodejs spawn

Node.js 的子进程 (child_process) 模块下有一 spawn 函数&#xff0c;可以用于调用系统上的命令&#xff0c;如在 Linux, macOS 等系统上&#xff0c;我们可以执行如下代码来调用通用的 npm 命令。 const spawn require(child_process).spawn; spawn(npm, {stdio: inherit …

利用JavaScript实现ISO周日历[]

基础知识 阳历&#xff1a; 就是以太阳来计算日期的一类历法&#xff1b;阴历&#xff1a; 就是以月亮来计算日期的一类历法&#xff1b;公历&#xff1a; 属阳历的一种&#xff0c;我国现在使用的就是公历&#xff1b;农历&#xff1a; 我国的农历是一种阴阳合历&#xff0c;…

eclipse启动无法找到类(自定义监听器)

一.报错 二.排查 1.首先检查代码是否有问题 本人报错是找不到监听器&#xff0c;故检查监听器的代码和web.xml文件是否有问题 public class DoorListener implements ServletContextListener 监听器是否继承并实现ServletContextListener中的方法。 web.xml中&#xff1a; &…

linux 服务器进程、端口查找,nginx 配置日志查找,lsof 命令详解

一 、根据端口号 查看文件的部署位置 1.1 使用查看端口号对应的进程信息 方式一 &#xff1a; 使用netstat命令 netstat -tuln | grep 端口号-t&#xff1a;显示TCP连接 -u&#xff1a;显示UDP连接 -l&#xff1a;仅显示监听状态的连接 -n&#xff1a;以数字形式显示端口…

【EI会议征稿】第四届机械设计与仿真国际学术会议(MDS 2024)

【高录用快检索】第四届机械设计与仿真国际学术会议&#xff08;MDS 2024) 2024 4th International Conference on Mechanical Design and Simulation 2024年第四届机械设计与仿真国际学术会议&#xff08;MDS 2024) 将于2024年03月01-03日在中国西安召开。MDS 2024将围绕“…

面试必考精华版Leetcode2542. 最大子序列的分数

题目&#xff1a; 代码&#xff08;首刷看解析 2023年11月17日&#xff09;&#xff1a; class Solution { public:long long maxScore(vector<int>& nums1, vector<int>& nums2, int k) {int n nums1.size();typedef pair<int,int> pii;// int有序…

GitHub访问不了,教你一招,不用开代理就可以访问

1.浏览器上输入网址&#xff1a;ipaddress.com 2.把GitHub地址复制到搜索框 3.搜索 4.一直往下拉直到找到GitHub的IP 5.将ip配置到本地host中&#xff0c;就可以了

表单演示设计,支持自定义页面背景!丨三叠云

表单演示 路径 表单设置 >> 表单演示 功能简介 1.「表单演示」内「数据演示设计」内增加页面背景设置模块。用户可配置页面的背景&#xff0c;目前支持单色和图片设置&#xff0c;满足用户在表单演示时多风格需求。 功能示例&#xff1a; 2.「表单演示」增加「演示设…