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():返回上下文的截止时间。如果存在截止时间,oktrue,否则为 false
  • Done():返回一个通道,该通道关闭时表示上下文被取消或者超过了截止时间。
  • Err():返回上下文取消的原因。如果上下文没有被取消,则返回 nil
  • Value(key):返回与给定 key 关联的值。这允许在上下文中传递请求范围的数据。

2. 创建上下文

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

ctx := context.Background()

可以使用 context.WithCancelcontext.WithTimeoutcontext.WithDeadlinecontext.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.WithTimeoutcontext.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()

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


声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。

Author: mengbin

blog: mengbin

Github: mengbin92

cnblogs: 恋水无意


go 上下文:context.Context的更多相关文章

  1. ZeroMQ接口函数之 :zmq_term - 终结ZMQ环境上下文(context)

    ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_term zmq_term(3) ØMQ Manual - ØMQ/4.1.0 Name zmq_term - 终 ...

  2. Tomcat部署web项目,虚拟目录,上下文(Context),WEB-INF,web.xml,servlet,404

    Web项目的uri模型大致如下: http://localhost:8080 (/context) (/resource) 站点/上下文/资源 一. Tomcat中指定上下文(Context) 方法一 ...

  3. javascript作用域(Scope),简述上下文(context)和作用域的定义

    网页制作Webjx文章简介:这篇文章将正面解决这个问题:简述上下文(context)和作用域的定义,分析可以让我们掌控上下文的两种方法,最后深入一种高效的方案,它能有效解决我所碰到的90%的问题. 作 ...

  4. Android开发之Android Context,上下文(Activity Context, Application Context)

    转载:http://blog.csdn.net/lmj623565791/article/details/40481055 1.Context概念Context,相信不管是第一天开发Android,还 ...

  5. 层叠上下文 Stacking Context

    层叠上下文 Stacking Context 在CSS2.1规范中,每个盒模型的位置是三维的,分别是平面画布上的x轴,y轴以及表示层叠的z轴.对于每个html元素,都可以通过设置z-index属性来设 ...

  6. (转)Docker镜像构建上下文(Context)

    镜像构建上下文(Context) Docker在构建镜像时,如果注意,会看到 docker build 命令最后有一个 ... 表示当前目录,而 Dockerfile 就在当前目录,因此不少初学者以为 ...

  7. Docker镜像构建上下文(Context)

    镜像构建上下文(Context) Dicker在构建镜像时,如果注意,会看到 docker build 命令最后有一个 ... 表示当前目录,而 Dockerfile 就在当前目录,因此不少初学者以为 ...

  8. Flask 上下文(Context)原理解析

    :first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...

  9. 上下文(Context)和作用域(Scope)

    函数的每次调用都有与之紧密相关的作用域和上下文.从根本上来说,作用域是基于函数的,而上下文是基于对象的. 换句话说,作用域涉及到所被调用函数中的变量访问,并且不同的调用场景是不一样的.上下文始终是th ...

  10. OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式

    在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...

随机推荐

  1. 人工智能如何应对 DevOps 监控和可观测性挑战

    自 ChatGPT 横空出世之后,AIGC 已成为不可逆转的时代浪潮.在之前的文章中,我们介绍了DevOps 领域中AI的用例,需要回顾可以点击下方链接.在本篇文章中,我将简单聊聊人工智能(AI)如何 ...

  2. VScode 中golang 基准测试 go test -bench .

    目的:基准测试的主要目的是比较不同实现方式之间的性能差异,找出性能瓶颈. 1 准备以_test.go结尾文件和导入testing包 在命名文件时需要让文件必须以_test结尾,在文件中导入testin ...

  3. http头部字段Origin和Access-Control-Allow-Origin解决请求跨域

    Http协议中请求头和响应头携带了很多信息,其中 请求头 Origin,响应头 Access-Control-Allow-Origin 与跨域有关. 为了验证跨域,要将客户端和服务端分配在不同端口,这 ...

  4. docker网络 bridge 与overlay 模式

    转载请注明出处: 1.bridge网络模式 工作原理:  在Bridge模式中,Docker通过创建一个虚拟网络桥接器(bridge)将容器连接到主机上的物理网络接口.每个容器都会被分配一个IP地址, ...

  5. 最常用的Linux命令

    1. tar 创建一个新的tar文件 $ tar cvf archive_name.tar dirname/ 解压tar文件 $ tar xvf archive_name.tar 查看tar文件 $ ...

  6. MindSponge分子动力学模拟——安装与使用(2023.08)

    技术背景 昇思MindSpore是由华为主导的一个,面向全场景构建最佳昇腾匹配.支持多处理器架构的开放AI框架.MindSpore不仅仅是软件层面的工具,更重要的是可以协同华为自研的昇腾Ascend平 ...

  7. 两种方式,轻松实现ChatGPT联网

    两种方式效果: 方式一:浏览器搜索内嵌插件 方式二:官方聊天页内嵌插件 首先,要有一个谷歌浏览器,然后再安装一个叫ChatGPT for Google,直接在谷歌里搜一下就能找,也可以Chrome应用 ...

  8. 关于ChatGPT的一些闲扯淡(1)

    这篇写的有点迟了,前者子ChatGPT正火的时候,懒病发作一直拖延.今天对ChatGPT做一个简单的讨论,也是把学习的心得和大家分享一下. 首先什么是GPT,英文全称是Generative Pretr ...

  9. 使用 Rancher 安装 K8s 集群

    舞台环境 Ubuntu 22.04.2 LTS Docker 24.0.2 2GB RAM或者更多 CPU 2核心或者更多 Rancher 2.6.9 测试环境中,我准备了两台 Ubuntu 服务器, ...

  10. Maven关联本地已有仓库的方法

    1. 将本地仓库目录localwarehouse进行压缩为localwarehouse.rar. 2. 将localwarehouse.rar解压到D:\maven文件夹中,然后在setting.xm ...