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