Context上下文

Context的出现是为了解决在大型应用程序中的并发环境下,协调和管理多个goroutine之间的通信、超时和取消操作的问题。它提供了一种标准化的机制,以便在程序的不同部分之间传递请求相关的值,并且可以在整个调用链中传播和取消这些值。

Context的主要目的是:

  • 传递请求范围的值:通过Context,可以在不同的函数调用中传递请求相关的值,例如请求ID、用户认证信息、日志记录器等。这样可以避免在函数之间显式传递这些值,使代码更加清晰简洁。
  • 控制并发操作:通过Context的取消信号,可以通知相关的goroutine停止运行并返回,从而实现对并发操作的控制。这对于处理长时间运行的操作或避免资源泄漏非常有用。
  • 传播和继承:通过Context,可以在整个调用链中传播和继承请求范围的值和取消信号,而无需显式地传递它们。这样可以减少代码中的重复操作,并确保所有相关的goroutine都能收到相同的上下文信息。

总而言之,Context的出现是为了提供一种统一的机制,用于管理并发操作、传递请求相关的值和控制操作的超时和取消。它简化了并发编程模型,提高了代码的可读性、可维护性和可测试性。

1. Context接口定义

Deadline() (deadline time.Time, ok bool)deadlineoktruefalseDone() <-chan struct{}<-chan struct{}Err() errornilValue(key interface{}) interface{}keyinterface{}nil

2. 错误设置

在上述代码中,定义了两个预定义的错误变量:Canceled和DeadlineExceeded,用于表示上下文取消和超时。

CanceledContext.Errerrors.New
DeadlineExceededContext.ErrdeadlineExceededErrorerror
Error()Timeout()trueTemporary()true

3. emptyCtx

emptyCtx
emptyCtxemptyCtxemptyCtx
emptyCtxstruct{}emptyCtx

该空上下文在一些特殊情况下使用,例如作为根上下文或默认上下文,在没有显式提供上下文的情况下,可以使用它来代替。由于其不可取消、没有值和截止时间的特性,它在某些场景下提供了一个空的占位符上下文实例。

4. 两个emptyCtx

4.1. Background

Background
BackgroundBackgroundBackground
BackgroundBackground

4.2. TODO

TODOcontext.TODO
TODOTODO

5. CancleFun

CancelFuncCancelFuncCancelFuncCancelFunc
CancelFunccontext.WithCancelcontext.WithDeadlinecontext.WithTimeoutCancelFunc
CancelFuncCancelFunc
CancelFunc

6. cancleCtx

cancelCtxcontextContext
cancelCtx
ContextcancelCtxContextmusync.Mutexdoneatomic.Valuechan struct{}nilchildrenmap[canceler]struct{}WithCancelWithDeadlineWithTimeoutnilerrerrornilcauseerrornil
cancelCtxcanceldoneerrcancelchildren

这种基于取消机制的上下文类型可以用于在多个 goroutine 之间传递取消信号,使得相关的操作可以在需要时及时终止。

7. WithCancel

WithCancel
DonecancelDoneDonecancelWithCancel

 wangyufan@wangcomputerair MINGW64 /d/goworkplace/src/github.com/context (master)
 $ go run .
 执行定时任务...
 执行定时任务...
 执行定时任务...
 执行定时任务...
 执行定时任务...
 定时任务被取消

ctxcancelcancel
context.WithCancel()

8. WithDeadline

WithDeadlineparentdDoneDoneDone
cancel
WithDeadline
time.Now()time.Duration
WithDeadline
dDoneDoneDonecancelWithDeadline

 wangyufan@wangcomputerair MINGW64 /d/goworkplace/src/github.com/context (master)
 $ go run .
 执行任务...
 执行任务...
 执行任务...
 执行任务...
 执行任务...
 任务被取消: context deadline exceeded

context.WithDeadline()ctxcanceltime.Now().Add(5*time.Second)cancel
context.WithDeadline()

9. WithTimeOut

WithTimeoutcontextparenttimeout
WithDeadlineWithDeadline
WithTimeouttime.Duration
WithTimeout

需要注意的是,超时时间应该是一个非负值。如果超时时间为零或负值,表示立即超时,即操作将立即取消。

 wangyufan@wangcomputerair MINGW64 /d/goworkplace/src/github.com/context (master)
 $ go run .
 执行任务...
 执行任务...
 执行任务...
 执行任务...
 执行任务...
 任务被取消: context deadline exceeded

context.WithTimeout()ctxcancel5*time.Secondcancel
context.WithTimeout()

10. WithValue

WithValuecontextparent(key, val)
parentkeynilkey==
valueCtxkeyvalvalueCtxcontext
valueCtxContext
WithValueWithValue

 wangyufan@wangcomputerair MINGW64 /d/goworkplace/src/github.com/context (master)
 $ go run .
 处理请求,用户ID: 123, 用户名: Alice
 执行其他操作,用户ID: 123, 用户名: Alice

parentcontext.WithValue()User{ID: 123, Name: "Alice"}ctxprocessRequest(ctx)
processRequestotherFunction(ctx)
otherFunction
context.WithValue()