Golang 中的 context.Context 是什么?如何使用?

context.Context 是 Golang 在标准库中提供的一个重要接口。它主要用于在远程调用或接口中传递截止时间、取消信号等上下文信息。

context.Context 主要有以下几个作用:

  1. 在一个树结构中传播上下文,用于多 goroutine 之间的超时控制、取消信号等;
  2. 定时器,获取一个上下文可能被取消的截止时间;
  3. 传播用户定义的 request-scoped 数据;

Context 接口定义如下:

type Context interface {
    // Deadline返回当前上下文被取消的时间,如果没有设置截止时间会返回一个ok值false
    Deadline() (deadline time.Time, ok bool)

    // Done返回一个Channel,当这个上下文被取消或超时的时候会关闭该Channel
    Done() <-chan struct{}

    // Err返回当前上下文结束的原因,它只会在Done返回的Channel被关闭的时候有效
    Err() error

    // Value返回与键绑定的值,主要用于传递请求域数据
    Value(key interface{}) interface{} 
} 

我们通常不会直接定义 Context 类型,而是使用标准库中提供的几种实现:

  1. context.Background():空上下文,所有新的上下文都是从这个开始的。
  2. context.TODO():推迟使用具体的上下文,目前还不清楚使用什么上下文。
  3. context.WithCancel(parent):从父上下文派生一个可取消的子上下文。
  4. context.WithDeadline(parent, deadline):从父上下文派生一个到期时间的子上下文。
  5. context.WithTimeout(parent, timeout):从父上下文派生一个带超时的子上下文。
  6. context.WithValue(parent, key, val):从父上下文派生一个携带值的子上下文。

例如:

// WithCancel
ctx, cancel := context.WithCancel(context.Background())
doSomething(ctx, ...)

// 取消操作
cancel()  

// WithDeadline
ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(50*time.Millisecond))
select {
case <-ctx.Done():
    // 处理超时...
case <-时间到:
}

// WithValue
ctx := context.WithValue(context.Background(), key, value)
// 在其他goroutine中获取值
value := ctx.Value(key) 

所以总结来说,context.Context 提供了一种在程序调用的不同层传递截止时间、取消信号和其它请求域数据的方式。这使得我们可以更加灵活和模块化地设计 API。
context 包正在慢慢成为 Golang 标准库中另一个至关重要的包,它彻底解决了 Golang 作为服务端语言在复杂系统或服务中的并发与接口超时控制等问题。