美文网首页
golang context

golang context

作者: wncbbnk | 来源:发表于2018-04-21 21:42 被阅读0次

overview

Package context defines the Context type, which carries deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.

Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context. The chain of function calls between them must propagate the Context, optionally replacing it with a derived Context created using WithCancel, WithDeadline, WithTimeout, or WithValue. When a Context is canceled, all Contexts derived from it are also canceled.

每个发给server的请求都应该创建一个Context,每个外部调用都应该有一个Context参数。它们之间的函数调用链必须支持从Context中衍生出Context。可以用WithCancel, WithDeadline, WithTimeout, 或者WithValue函数从Context衍生出Context。当一个Context被取消后,所有从这个Context衍生出得Context都会被取消。

The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and return a derived Context (the child) and a CancelFunc. Calling the CancelFunc cancels the child and its children, removes the parent's reference to the child, and stops any associated timers. Failing to call the CancelFunc leaks the child and its children until the parent is canceled or the timer fires. The go vet tool checks that CancelFuncs are used on all control-flow paths.

WithCancel, WithDeadline, WithTimeout函数以一个Context(父)为参数,返回一个衍生的Context(子)与一个函数CancelFunc。调用这个CancelFunc会取消子Context以及以这个子Context为父的子Context,删除父Context对子Context的引用,并且停止相关的timers。如果不调用CancelFunc会导致这个子Context与子Context的子Context泄露,直到父Context被取消或者timer到时间触发。工具go vet可以检查是否CancelFuncs在所有控制流路径上被调用。

Programs that use Contexts should follow these rules to keep interfaces consistent across packages and enable static analysis tools to check context propagation:

Do not store Contexts inside a struct type; instead, pass a Context explicitly to each function that needs it. The Context should be the first parameter, typically named ctx:

不要把Context包含在一个struct中。需要把Context当成一个独立的参数,默认是第一个参数,名字一般命名为ctx:

func DoSomething(ctx context.Context, arg Arg) error {
    // ... use ctx ...
}

Do not pass a nil Context, even if a function permits it. Pass context.TODO if you are unsure about which Context to use.

即使函数允许传一个nil的Context,也不要这么做。如果不知道该用哪一个Context,可以用context.TODO。

Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.

用context的Value只能用于在processes或者APIs之间传输的请求域数据,不要用于其他的随意的数据。

The same Context may be passed to functions running in different goroutines; Contexts are safe for simultaneous use by multiple goroutines.

相同的Context可以传给在不同的goroutines里的函数,Context对于在多协程的并发场景下是安全的。

See https://blog.golang.org/context for example code for a server that uses Contexts.

Variables

Canceled is the error returned by Context.Err when the context is canceled.

var Canceled = errors.New("context canceled")

DeadlineExceeded is the error returned by Context.Err when the context's deadline passes.

var DeadlineExceeded error = deadlineExceededError{}

type CancelFunc

A CancelFunc tells an operation to abandon its work. A CancelFunc does not wait for the work to stop. After the first call, subsequent calls to a CancelFunc do nothing.

type CancelFunc func()

type Context

A Context carries a deadline, a cancelation signal, and other values across API boundaries.
Context's methods may be called by multiple goroutines simultaneously.

Context的方法可以在多个协程中并发的调用

type Context interface {
    // Deadline returns the time when work done on behalf of this context
    // should be canceled. Deadline returns ok==false when no deadline is
    // set. Successive calls to Deadline return the same results.
    /* 
     *Deadline返回这个Context应该被取消的时间。如果ok==false,说明没有设置Deadline。
     */
    Deadline() (deadline time.Time, ok bool)

    // Done returns a channel that's closed when work done on behalf of this
    // context should be canceled. Done may return nil if this context can
    // never be canceled. Successive calls to Done return the same value.
    /*
     *  Done返回一个channel,如果这个context应该被取消,那么这个返回的channel状态为被关闭。如果这个context不应该被取消,那么可能为nil。对Done函数的成功调用将返回相同的返回值。
     */
    //
    // WithCancel arranges for Done to be closed when cancel is called;
    // WithDeadline arranges for Done to be closed when the deadline
    // expires; WithTimeout arranges for Done to be closed when the timeout
    // elapses.
    //
    // Done is provided for use in select statements:
    //
    //  // Stream generates values with DoSomething and sends them to out
    //  // until DoSomething returns an error or ctx.Done is closed.
    //  func Stream(ctx context.Context, out chan<- Value) error {
    //      for {
    //          v, err := DoSomething(ctx)
    //          if err != nil {
    //              return err
    //          }
    //          select {
    //          case <-ctx.Done():
    //              return ctx.Err()
    //          case out <- v:
    //          }
    //      }
    //  }
    //
    // See https://blog.golang.org/pipelines for more examples of how to use
    // a Done channel for cancelation.
    Done() <-chan struct{}

    // If Done is not yet closed, Err returns nil.
    // If Done is closed, Err returns a non-nil error explaining why:
    // Canceled if the context was canceled
    // or DeadlineExceeded if the context's deadline passed.
    // After Err returns a non-nil error, successive calls to Err return the same error.
    Err() error

    // Value returns the value associated with this context for key, or nil
    // if no value is associated with key. Successive calls to Value with
    // the same key returns the same result.
    //
    // Use context values only for request-scoped data that transits
    // processes and API boundaries, not for passing optional parameters to
    // functions.
    //
    // A key identifies a specific value in a Context. Functions that wish
    // to store values in Context typically allocate a key in a global
    // variable then use that key as the argument to context.WithValue and
    // Context.Value. A key can be any type that supports equality;
    // packages should define keys as an unexported type to avoid
    // collisions.
    //
    // Packages that define a Context key should provide type-safe accessors
    // for the values stored using that key:
    //
    //  // Package user defines a User type that's stored in Contexts.
    //  package user
    //
    //  import "context"
    //
    //  // User is the type of value stored in the Contexts.
    //  type User struct {...}
    //
    //  // key is an unexported type for keys defined in this package.
    //  // This prevents collisions with keys defined in other packages.
    //  type key int
    //
    //  // userKey is the key for user.User values in Contexts. It is
    //  // unexported; clients use user.NewContext and user.FromContext
    //  // instead of using this key directly.
    //  var userKey key
    //
    //  // NewContext returns a new Context that carries value u.
    //  func NewContext(ctx context.Context, u *User) context.Context {
    //      return context.WithValue(ctx, userKey, u)
    //  }
    //
    //  // FromContext returns the User value stored in ctx, if any.
    //  func FromContext(ctx context.Context) (*User, bool) {
    //      u, ok := ctx.Value(userKey).(*User)
    //      return u, ok
    //  }
    Value(key interface{}) interface{}
}

func Background

func Background() Context

Background returns a non-nil, empty Context. It is never canceled, has no values, and has no deadline. It is typically used by the main function, initialization, and tests, and as the top-level Context for incoming requests.

Background返回一个non-nil、emptyContext. 这个Context不会被cancel,没有value,也没有deadline。一般被main函数、初始化函数、测试、或者为请求的顶层Context使用。

func TODO

func TODO() Context

TODO returns a non-nil, empty Context. Code should use context.TODO when it's unclear which Context to use or it is not yet available (because the surrounding function has not yet been extended to accept a Context parameter). TODO is recognized by static analysis tools that determine whether Contexts are propagated correctly in a program.

func WIthCancel

func WithCancel(parent Context) (ctx Context,  cancel CancelFunc)

WithCancel returns a copy of parent with a new Done channel. The returned context's Done channel is closed when the returned cancel function is called or when the parent context's Done channel is closed, whichever happens first.

WithCancel返回一个从parent复制而来的拥有新的Done channel的Context。如果cancel函数被执行,或者父Context的Done channel被关闭,任意一个发生,那么子Done Channel也会被关闭。

Canceling this context releases resources associated with it, so code should call cancel as soon as the operations running in this Context complete.

取消一个context会释放与之相关的资源,所代码应该当操作完成后尽早调用cancel。

example

This example demonstrates the use of a cancelable context to prevent a goroutine leak. By the end of the example function, the goroutine started by gen will return without leaking.
Code:

// gen generates integers in a separate goroutine and
// sends them to the returned channel.
// The callers of gen need to cancel the context once
// they are done consuming generated integers not to leak
// the internal goroutine started by gen.
gen := func(ctx context.Context) <-chan int {
    dst := make(chan int)
    n := 1
    go func() {
        for {
            select {
            case <-ctx.Done():
                return // returning not to leak the goroutine
            case dst <- n:
                n++
            }
        }
    }()
    return dst
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel() // cancel when we are finished consuming integers

for n := range gen(ctx) {
    fmt.Println(n)
    if n == 5 {
        break
    }
}

Output:

1
2
3
4
5

func WithDeadline

func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)

WithDeadline returns a copy of the parent context with the deadline adjusted to be no later than d. If the parent's deadline is already earlier than d, WithDeadline(parent, d) is semantically equivalent to parent. The returned context's Done channel is closed when the deadline expires, when the returned cancel function is called, or when the parent context's Done channel is closed, whichever happens first.

WithDeadline返回一个父context的拷贝,且新的context的deadline不会比d晚。如果父Context的deadline已经比d早,那么新的deadline也会为d(不能父deadline到了子的还没到)。返回的context的Done channel会在如下几种场景中cancel:如果deadline到期,如果cancel function被调用,如果父Context的Done channel被关闭。

Canceling this context releases resources associated with it, so code should call cancel as soon as the operations running in this Context complete.

example

This example passes a context with an arbitrary deadline to tell a blocking function that it should abandon its work as soon as it gets to it.

Code:

d := time.Now().Add(50 * time.Millisecond)
ctx, cancel := context.WithDeadline(context.Background(), d)

// Even though ctx will be expired, it is good practice to call its
// cancelation function in any case. Failure to do so may keep the
// context and its parent alive longer than necessary.
//即使ctx最终会过期,但是defer cancel()依然是个好习惯。
defer cancel()

select {
case <-time.After(1 * time.Second):
    fmt.Println("overslept")
case <-ctx.Done():
    fmt.Println(ctx.Err())
}

Output:

context deadline exceeded

func WithTimeout

func WithTimeout(parent Context, duration Time.Duration) (Context, CancelFunc)

WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).

Canceling this context releases resources associated with it, so code should call cancel as soon as the operations running in this Context complete:

func slowOperationWithTimeout(ctx context.Context) (Result, error) {
    ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
    defer cancel()  // releases resources if slowOperation completes before timeout elapses
    return slowOperation(ctx)
}

example

This example passes a context with a timeout to tell a blocking function that it should abandon its work after the timeout elapses.
Code:

// Pass a context with a timeout to tell a blocking function that it
// should abandon its work after the timeout elapses.
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel()

select {
case <-time.After(1 * time.Second):
    fmt.Println("overslept")
case <-ctx.Done():
    fmt.Println(ctx.Err()) // prints "context deadline exceeded"
}

Output:

context deadline exceeded

func WithValue

func WithValue(parent Context, key, val interface{}) (Context)

WithValue returns a copy of parent in which the value associated with key is val.

Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.

The provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys. To avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables' static type should be a pointer or interface.

提供的key必须是可以比较的,并且不能为string或者其他的内建的类型,以避免不同包使用context导致的冲突。使用WithValue需要定义自己的key类型。To avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables' static type should be a pointer or interface.

example

Code:

type favContextKey string

f := func(ctx context.Context, k favContextKey) {
    if v := ctx.Value(k); v != nil {
        fmt.Println("found value:", v)
        return
    }
    fmt.Println("key not found:", k)
}

k := favContextKey("language")
ctx := context.WithValue(context.Background(), k, "Go")

f(ctx, k)
f(ctx, favContextKey("color"))

Output:

found value: Go
key not found: color

相关文章

  • Golang Context分析

    [TOC] Golang Context分析 Context背景 和 适用场景 golang在1.6.2的时候还没...

  • 利用context保存数据

    context[https://golang.org/pkg/context/#example_WithValue...

  • Golang 之context库用法

    1. context Golang 中的context 是Go语言在 golang1.7 发布时新增的标准包目的...

  • Golang Context 详细原理和使用技巧

    Golang Context 详细原理和使用技巧 Context 背景 和 适用场景 Context 的背景 Go...

  • Golang context初探

    什么是context 从go1.7开始,golang.org/x/net/context包正式作为context包...

  • golang context

    overview Package context defines the Context type, which ...

  • golang context

    https://yq.aliyun.com/articles/69662https://deepzz.com/po...

  • golang context

    在 go1.7 及以上版本 context 包被正式列入官方库中,所以我们只需要import "context"就...

  • golang context

    先翻译一下go官方文档 翻译 总结一下: 第一点:所有的请求都要保存一个context,被调用的方法应该也要一个c...

  • golang context

    最初接触golang http源码的时候就发现有一个比较特别的package context,并且在后面学习etc...

网友评论

      本文标题:golang context

      本文链接:https://www.haomeiwen.com/subject/cphxlftx.html