编程 `context`包是Go语言中的标准库,用于在并发环境中安全地传递上下文信息

2024-11-19 04:28:00 +0800 CST views 475

概述

context 包是 Go 语言中的一个常用标准库,用于在并发环境下在协程之间安全地传递某些上下文信息。它在处理并发任务时尤其有用,特别是在需要在多个协程之间共享或传递请求相关数据时。

一个经典的应用场景是服务器模型。当服务器处理接收到的请求时,通常需要并发地运行多个子任务,例如访问数据库、请求授权等。这些任务通常以协程的方式运行,即一个请求可能绑定了多个协程。这些协程需要共享某些与请求相关的数据;此外,当请求被撤销时,也需要有一种机制确保所有子协程能够安全地退出。context 包提供了这些功能。

Context 详解

Context 是一个上下文对象,用于携带超时、取消信号以及传递请求范围内的数据。其定义如下:

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key interface{}) interface{}
}

Context 的方法

  • Deadline():返回 Context 被取消的时间和一个布尔值,若 Context 没有设置超时则布尔值为 false
  • Done():返回一个通道,当 Context 被取消或超时时,该通道会被关闭。
  • Err():返回 Context 被取消的原因,若未被取消则返回 nil
  • Value(key interface{}) interface{}:用于在上下文中存储和获取值。

创建 Context

context 包中,有两种基础的 Context,分别通过 BackgroundTODO 函数创建。函数声明如下:

func Background() Context
func TODO() Context

通常情况下,使用 Background 函数即可。调用 Background 函数会返回一个空的 Context,该 Context 不能直接使用,只是作为所有其他 Context 的根 Context。所有其他 Context 都是从这个基础 Context 衍生出来的。

衍生 Context

要创建可使用的 Context,可以使用以下三种函数从根 Context 衍生出新的 Context。由于 Context 是树状结构的,所以也可以在任何一个 Context 上创建子 Context

WithCancel

WithCancel 函数返回一个可以取消的 Context。函数声明如下:

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
  • parent:父 Context
  • ctx:返回的子 Context
  • cancel:一个函数,用于向 Context 发送取消信号。

由于 Context 存在继承关系,当父 Context 被取消时,其所有子 Context 也会被取消。

CancelFunc 和 Done

CancelFunc 用于取消 Context,而 Done 方法返回一个通道,当 Context 被取消时,该通道会被关闭。以下是一个常见的代码模式:

func Stream(ctx context.Context, out chan<- Value) error {
    for {
        v, err := DoSomething(ctx)
        if err != nil {
            return err
        }
        select {
        case <-ctx.Done():
            return ctx.Err()
        case out <- v:
        }
    }
}

在这个例子中,子协程会不断运行并检查当前任务是否被取消,若被取消则结束任务并返回。

WithDeadline 和 WithTimeout

WithDeadlineWithTimeout 两个函数分别用于创建有截止时间和超时的 Context,即使不主动取消,当达到截止时间或超时时,Context 也会自动接收到取消信号。函数声明如下:

func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)

WithCancel 类似,这两类 Context 会在超时后自动取消。

WithValue

WithValue 函数用于在同一个上下文中传递数据,这是一个不可取消的 Context。其函数声明如下:

func WithValue(parent Context, key, val interface{}) Context
  • keyval:用于保存数据的键值对。可以通过 Context.Value(key) 获取存储的值。

使用建议

  • 不要在子协程中取消父 Context:子协程不应主动取消父协程的 Context,否则可能导致不可预知的后果。
  • 显式传递 ContextContext 应该作为参数显式传递,而不是作为某个类型的字段,这样可以避免上下文被不小心修改或遗忘。

通过 context 包,可以有效管理并发任务之间的共享数据、任务超时和取消信号,确保在复杂的并发环境下任务能够按预期运行。

复制全文 生成海报 Go语言 并发编程 上下文管理

推荐文章

rangeSlider进度条滑块
2024-11-19 06:49:50 +0800 CST
黑客帝国代码雨效果
2024-11-19 01:49:31 +0800 CST
Nginx 反向代理
2024-11-19 08:02:10 +0800 CST
JavaScript 策略模式
2024-11-19 07:34:29 +0800 CST
2024年微信小程序开发价格概览
2024-11-19 06:40:52 +0800 CST
16.6k+ 开源精准 IP 地址库
2024-11-17 23:14:40 +0800 CST
windows安装sphinx3.0.3(中文检索)
2024-11-17 05:23:31 +0800 CST
Python 获取网络时间和本地时间
2024-11-18 21:53:35 +0800 CST
php curl并发代码
2024-11-18 01:45:03 +0800 CST
MySQL 优化利剑 EXPLAIN
2024-11-19 00:43:21 +0800 CST
程序员茄子在线接单