Go语言并发编程-Context上下文

[复制链接]
发表于 2026-2-20 22:14:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Context上下文

Context概述

Go 1.7 标准库引入 context,译作“上下文”,精确说它是 goroutine 的上下文,包罗 goroutine 的运行状态、环境、现场等信息。
context 重要用来在 goroutine 之间通报上下文信息,包罗:取消信号、超时时间、制止时间、k-v 等。
随着 context 包的引入,标准库中许多接口因此加上了 context 参数,比方 database/sql 包。context 险些成为了并发控制和超时控制的标准做法。
在一组goroutine 之间通报共享的值、取消信号、deadline是Context的作用。
以典范的HTTPServer为例:


我们以 Context II为例,若没有上下文信号,当此中一个goroutine出现标题时,其他的goroutine不知道,还会继承工作。如许的无效的goroutine积攒起来,就会导致goroutine雪崩,进而导致服务宕机!
没有同步信号:


增长同步信号:

参考:Context通报取消信号 小结。
Context 核心结构

context.Context 是 Go 语言在 1.7 版本中引入标准库的接口,该接口界说了四个必要实现的方法:
  1.  type Context interface {
  2.      // 返回被取消的时间
  3.      Deadline() (deadline time.Time, ok bool)
  4.      // 返回用于通知Context完结的channel
  5.      // 当这个 channel 被关闭时,说明 context 被取消了
  6.      // 在子协程里读这个 channel,除非被关闭,否则读不出来任何东西
  7.      Done() <-chan struct{}
  8.      // 返回Context取消的错误
  9.      Err() error
  10.      // 返回key对应的value
  11.      Value(key any) any
  12.  }
复制代码
除了Context接口,还存在一个canceler接口,用于实现Context可以被取消:
  1.  type canceler interface {
  2.      cancel(removeFromParent bool, err error)
  3.      Done() <-chan struct{}
  4.  }
复制代码
除了以上两个接口,另有4个预界说的Context范例:
  1.  // 空Context
  2.  type emptyCtx int
  3.  ​
  4.  // 取消Context
  5.  type cancelCtx struct {
  6.      Context
  7.      mu       sync.Mutex            // protects following fields
  8.      done     atomic.Value          // of chan struct{}, created lazily, closed by first cancel call
  9.      children map[canceler]struct{} // set to nil by the first cancel call
  10.      err      error                 // set to non-nil by the first cancel call
  11.  }
  12.  ​
  13.  // 定时取消Context
  14.  type timerCtx struct {
  15.      cancelCtx
  16.      timer *time.Timer // Under cancelCtx.mu.
  17.  ​
  18.      deadline time.Time
  19.  }
  20.  ​
  21.  // KV值Context
  22.  type valueCtx struct {
  23.      Context
  24.      key, val any
  25.  }
  26.  ​
复制代码
默认(空)Context的使用

context 包中最常用的方法是 context.Background、context.TODO,这两个方法都会返回预先初始化好的私有变量 background 和 todo,它们会在同一个 Go 步伐中被复用:

      
  • context.Background, 是上下文的默认值,全部其他的上下文都应该从它衍生出来,在多数环境下,假如当前函数没有上下文作为入参,我们都会使用 context.Background 作为起始的上下文向下通报。
      
  • context.TODO,是一个备用,一个context占位,通常用在并不知道通报什么 context的环境。

使用示例,database/sql包中的实验:
  1.  func (db *DB) PingContext(ctx context.Context) error
  2.  func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (Result, error)
  3.  func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error)
  4.  func (db *DB) QueryRowContext(ctx context.Context, query string, args ...any) *Row
复制代码
方法,此中第一个参数就是context.Context。
比方:使用时:
  1.  db, _ := sql.Open("", "")
  2.  query := "DELETE FROM `table_name` WHERE `id` = ?"
  3.  db.ExecContext(context.Background(), query, 42)
复制代码
固然,单独 database.sql包中,也支持不通报context.Context的方法。功能同等,但缺失了context.Context干系功能。
  1.  func (db *DB) Exec(query string, args ...any) (Result, error)
复制代码
context.Background 和 context.TODO 返回的都是预界说好的 emptyCtx 范例数据,其结构如下:
  1.  // 创建方法
  2.  func Background() Context {
  3.      return background
  4.  }
  5.  func TODO() Co
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表