contextWaitGroupcontextgoroutine
1. 接口定义
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <- chan struct{}
Err() error
Value(key interface{}) interface{}
}
deadlineok==falseselect-casecase <-context.Done():contextDone()goroutinecontextDone()nilcontextcontextdeadlinecontext deadline exceededcontext cancelednilcontextgoroutinegoroutineValue()keymapValue
2. 使用
contextcontexthandle
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
go handle(ctx, 500*time.Millisecond)
select {
case <-ctx.Done():
fmt.Println("main", ctx.Err())
}
}
func handle(ctx context.Context, duration time.Duration) {
select {
case <-ctx.Done():
fmt.Println("handle", ctx.Err())
case <-time.After(duration):
fmt.Println("process request with", duration)
}
}
output:
process request with 500ms
main context deadline exceeded
contextselect<-time.After(duration):<-ctx.Done()process request with 500ms<-ctx.Done()main context deadline exceeded
400*time.Millisecond
main context deadline exceeded
B:
main context deadline exceeded
handle context deadline exceeded
C:
process request with 500ms
main context deadline exceeded
D:
process request with 500ms
E:
handle context deadline exceeded
main context deadline exceeded
答案是:A、B、E
可能出现这3种,而不是1种的原因是和调度器有关。
context
backgroundtodonew(emptyCtx)context.emptyCtxcontext.Background()context.TODO()context.WithCancelcontext.timerCtxcontext.WithCancel()context.Context()contextcontext.WithDeadline()context.WithTimeout()context.WithValue()context.valueCtxKeyValue
func (c *valueCtx) Value(key interface{}) interface{} {
if c.key == key {
return c.val
}
return c.Context.Value(key)
}