在 Go 编程语言中,context 包提供了一个用于在 goroutine 之间传递上下文信息的方法。它通常用于控制 goroutine 的生命周期、传递请求范围内的数据、以及处理超时或取消信号。context 包的核心是 Context 接口和与之相关的函数和方法。

Context 接口

Context 接口定义如下:

type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
  • Deadline() 返回上下文会被自动取消的时间,以及是否存在这样的时间。
  • Done() 返回一个 chan struct{},当上下文被取消或超时时,这个通道会被关闭。
  • Err() 返回上下文被取消的原因。如果 Done 通道已经关闭,它会返回一个非 nil 的错误。
  • Value(key interface{}) 返回与上下文关联的键对应的值。

创建 Context

通常有四种方式来创建一个 Context

  1. context.Background()
  2. context.TODO()
  3. context.WithCancel(parent Context)
  4. context.WithTimeout(parent Context, timeout time.Duration)
  5. context.WithDeadline(parent Context, deadline time.Time)
  6. context.WithValue(parent Context, key, val interface{})

例子

使用 context.Background()

context.Background() 返回一个空的上下文,通常用于主函数、初始化和测试。

ctx := context.Background()

使用 context.WithCancel

context.WithCancel 返回一个派生上下文和一个取消函数。当调用取消函数时,派生上下文的 Done 通道会被关闭。

ctx, cancel := context.WithCancel(context.Background())
defer cancel() // 确保资源被释放 go func() {
// 模拟一些工作
time.Sleep(2 * time.Second)
cancel() // 取消上下文
}() <-ctx.Done() // 等待上下文被取消
fmt.Println("Context canceled:", ctx.Err())

使用 context.WithTimeout

context.WithTimeout 返回一个派生上下文和一个取消函数。指定的超时时间过后,派生上下文的 Done 通道会被关闭。

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() select {
case <-time.After(5 * time.Second):
fmt.Println("Operation completed")
case <-ctx.Done():
fmt.Println("Timeout:", ctx.Err())
}

使用 context.WithValue

context.WithValue 返回一个带有键值对的派生上下文,用于在请求的生命周期中传递数据。

type keyType string

func main() {
ctx := context.WithValue(context.Background(), keyType("userID"), 12345)
ProcessRequest(ctx)
} func ProcessRequest(ctx context.Context) {
userID := ctx.Value(keyType("userID")).(int)
fmt.Println("User ID:", userID)
}

典型应用场景

  1. API 请求处理: 在处理 HTTP 请求时,传递上下文以管理超时和取消。
  2. 并发任务管理: 使用上下文来控制和取消多个并发任务。
  3. 传递请求范围的数据: 例如用户身份验证信息、跟踪 ID 等。

注意事项

  • Context 是不可变的,应当通过 context.WithCancel, context.WithTimeout, context.WithDeadline, context.WithValue 等函数创建新的派生上下文。
  • 不要将 Context 存储在结构体中,应当作为函数的第一个参数传递。
  • 尽量在短生命周期的请求中使用 Context,避免长时间持有上下文。

通过正确使用 context 包,可以编写出更健壮、更易于维护的并发程序。

Go context 介绍的更多相关文章

  1. Golang的Context介绍及其源码分析

    简介 在Go服务中,对于每个请求,都会起一个协程去处理.在处理协程中,也会起很多协程去访问资源,比如数据库,比如RPC,这些协程还需要访问请求维度的一些信息比如说请求方的身份,授权信息等等.当一个请求 ...

  2. Tomcat下server.xml中context介绍

    conf/Context.xml是Tomcat公用的环境配置;若在server.xml中增加<Context path="/test" docBase="D:\te ...

  3. Go context 介绍和使用

    context 上下文管理 context 翻译过来就是上下文管理,主要作用有两个: 控制 goroutine 的超时 保存上下文数据 WithTimeout 通过下面的一个简单的 http 例子进行 ...

  4. Android Context介绍

    转载(Android Context完全解析与各种获取Context方法):https://www.cnblogs.com/chenxibobo/p/6136693.html

  5. 理解Go Context机制

    1 什么是Context 最近在公司分析gRPC源码,proto文件生成的代码,接口函数第一个参数统一是ctx context.Context接口,公司不少同事都不了解这样设计的出发点是什么,其实我也 ...

  6. Android上下文Context

    Android上下文Context介绍 在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中时刻的在与它打交道,例如:Service.BroadcastReceiv ...

  7. Golang 高效实践之并发实践context篇

    前言 在上篇Golang高效实践之并发实践channel篇中我给大家介绍了Golang并发模型,详细的介绍了channel的用法,和用select管理channel.比如说我们可以用channel来控 ...

  8. Go实现海量日志收集系统(三)

    再次整理了一下这个日志收集系统的框,如下图 这次要实现的代码的整体逻辑为: 完整代码地址为: https://github.com/pythonsite/logagent etcd介绍 高可用的分布式 ...

  9. Flask类的属性和方法大全

    Flask Property__class____dict____doc____module__app_ctx_globals_classconfig_classdebugdefault_config ...

  10. OpenGL Windows 窗口程序环境搭建

    OpenGL环境搭建步骤: Downloading OpenGL 根据官网的说法: In all three major desktop platforms (Linux, macOS, and Wi ...

随机推荐

  1. 构建高可用性、高性能和可扩展的Zabbix Server架构

    简介 本教程讲解了一下如何设计构建一个高性能.高可靠.高扩展的Zabbix 监控集群. 架构图 架构图PDF下载: https://songxwn.com/file/Zabbix_HA.pdf Pig ...

  2. P9120 题解

    暴力容斥复活之路! \(k=1\) 这个你肯定会. \(k=2\) 大的放上去,小的放下来.简单贪心. \(k=3\) 考虑二分答案. 然后考虑判断是否合法. 令当前答案为 \(val\). 首先钦定 ...

  3. Linux 提权-SUID/SGID_2

    本文通过 Google 翻译 SUID | SGID Part-2 – Linux Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注释 ...

  4. Django详细笔记

    django 学习 特点 快速开发 安全性高 可伸缩性强 URL 组成部分 URL: 同意资源定位符 一个URL由以下几部分组成 scheme://host:port/path/?query-stri ...

  5. 使用Eclipse开发Vue——CodeMix够智能

    使用Eclipse开发Vue--CodeMix够智能 Eclipse的CodeMix插件允许您访问 VS Code和Code OSS扩展社区,以及 Webclipse 1.x 功能. Vue.js是构 ...

  6. [Unity] Dreamteck Splines实现沿路径移动功能

    Dreamteck Splines实现沿路径移动功能 最近有一个"让物体沿固定路径移动"的需求,因此接触到了Dreamteck Splines插件. Dreamteck Splin ...

  7. 10 pdf分享失败

    PC端分享pdf,复制粘贴pdf链接后跳转搜索首页

  8. leetcode简单(数组,字符串,链表):[66, 67, 70, 83, 121, 141, 160, 169, ,206, 338]

    目录 66. 加一 67. 二进制求和 70. 爬楼梯 83. 删除排序链表中的重复元素 121. 买卖股票的最佳时机 141. 环形链表 160. 相交链表 169. 多数元素 206. 反转链表 ...

  9. Linux 文本文件编辑相关命令简介【Linux 常用命令系列二】

    〇.前言 本文介绍了如何通过 vim 命令,对文本文件进行打开.编辑.保存等相关操作,并通过简单的示例演示了常用用法. 一.关于文本文件的操作 1.1 打开,查看(cat).编辑(vim) 打开文本文 ...

  10. java面试一日一题:讲下ThreadLocal

    问题:请讲下ThreadLocal 分析:首先要了解ThreadLocal的基本原理:其次要理解ThreadLocal发生内存泄漏的原因:最后ThreadLocal是如何做到线程隔离的 回答要点: 主 ...