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()