Quick Master Golang Context package, simple example

Source: Internet
Author: User
Tags comparable
This is a creation in Article, where the information may have evolved or changed.

Preview Catalog

  • Context principle
  • Follow the Rules
  • Context Pack
  • Withcancel Example
  • Withdeadline Example
  • withtimeout Example
  • Withvalue Example
  • Reference connection

For Golang Developers context (context) The package must not be unfamiliar. But most of the time, we are lazy only to see it, or can play a role, and will not delve into it.

Application Scenario : In the Go HTTP package Server, each request has a corresponding goroutine processing. The request handler function typically initiates additional goroutine access to the backend services, such as the database and the RPC service. the process used to handle a request goroutine typically requires access to some data that is specific to the request, such as the end user's authentication information, the authentication token, and the deadline for the request. When a request is canceled or timed out, all that is used to process the request goroutine should exit quickly, and then the system can release the goroutine resources that are occupied by the official blog.

Note: go1.6 Please use the previous version golang.org/x/net/context . go1.7and then moved to the standard library context .

Context principle

The call to the context should be chained, passed WithCancel , WithDeadline WithTimeout or WithValue derived from a new context. When the parent context is canceled, all of its derived context is canceled.

The pass context.WithXXX will return the new Context and Cancelfunc. Calling Cancelfunc cancels the descendant, removes the parent's reference to the descendant, and stops all timers. Failure to call Cancelfunc will leak the descendant until the parent is canceled or the timer triggers. go vetThe tool checks all process control paths using Cancelfuncs.

Follow the Rules

Follow these rules to keep the interfaces between packages consistent and enable static analysis tools to check context propagation.

    1. Do not put contexts in the struct, instead context it should be passed in as the first parameter, named ctx .func DoSomething(ctx context.Context,arg Arg)error { // ... use ctx ... }
    2. Do not pass in the Context even if the function allows it nil . If you do not know which Context to use context.TODO() .
    3. The value-related method using the context should only be used for metadata that is passed in the program and interface and requested, and should not be used to pass some optional arguments
    4. The same context can be passed to the different goroutine ; context is concurrency-safe.

Context Pack

Context structure.

// A Context carries a deadline, cancelation signal, and request-scoped values// across API boundaries. Its methods are safe for simultaneous use by multiple// goroutines.type Context interface {    // Done returns a channel that is closed when this Context is canceled    // or times out.    Done() <-chan struct{}    // Err indicates why this context was canceled, after the Done channel    // is closed.    Err() error    // Deadline returns the time when this Context will be canceled, if any.    Deadline() (deadline time.Time, ok bool)    // Value returns the value associated with key or nil if none.    Value(key interface{}) interface{}}
    • Done (), returns a channel. When times out or the Cancel method is called, it is close.
    • ERR (), returns an error. Why the context was canceled.
    • Deadline (), return the cutoff time and OK.
    • Value (), which returns the values.

All methods

func Background() Contextfunc TODO() Contextfunc WithCancel(parent Context) (ctx Context, cancel CancelFunc)func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)func WithValue(parent Context, key, val interface{}) Context

As you can see, the context is an interface that you want to use to implement its methods. Within the context package, we have implemented two empty context for us, which can be obtained by calling the background () and Todo () methods. They are generally used as the root of the context and are derived downward.

Withcancel Example

Withcancel returns a copy of the parent Context with a new done channel.

   229  func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {   230      c := newCancelCtx(parent)   231      propagateCancel(parent, &c)   232      return &c, func() { c.cancel(true, Canceled) }   233  }   234     235  // newCancelCtx returns an initialized cancelCtx.   236  func newCancelCtx(parent Context) cancelCtx {   237      return cancelCtx{   238          Context: parent,   239          done:    make(chan struct{}),   240      }   241  }

This example demonstrates the use of a removable context to prevent goroutine leaks. At the end of the sample function, defer calls the Cancel method, and Gen Goroutine returns without leaking.

package mainimport (    "context"    "fmt")func main() {    // 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        }    }}

Withdeadline Example

   369  func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {   370      if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {   371          // The current deadline is already sooner than the new one.   372          return WithCancel(parent)   373      }   374      c := &timerCtx{   375          cancelCtx: newCancelCtx(parent),   376          deadline:  deadline,   377      }   ......

It is clear that when the deadline of the derived sub-context is behind the parent context, a copy of the parent context is returned directly. Therefore, semantically equivalent is the parent.

The Withdeadline's deadline is adjusted to return a copy of the parent context no later than D. If the parent's cutoff date is earlier than D,withdeadline (parent, D) is semantically equivalent to the parent. Returns the context after which the completion of the channel closes after the end of the expiration date, when the cancellation function is called, or when the parent context completes the channel close, whichever occurs first.

Take a look at the official example:

package mainimport (    "context"    "fmt"    "time")func main() {    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.    defer cancel()    select {    case <-time.After(1 * time.Second):        fmt.Println("overslept")    case <-ctx.Done():        fmt.Println(ctx.Err())    }}

withtimeout Example

Withtimeout returns Withdeadline (parent, time. Now (). ADD (timeout)).

   436  func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {   437      return WithDeadline(parent, time.Now().Add(timeout))   438  }

Take a look at the official example:

package mainimport (    "context"    "fmt"    "time")func main() {    // 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"    }}

Withvalue Example

   454  func WithValue(parent Context, key, val interface{}) Context {   454      if key == nil {   455          panic("nil key")   456      }   457      if !reflect.TypeOf(key).Comparable() {   458          panic("key is not comparable")   459      }   460      return &valueCtx{parent, key, val}   461  }

Withvalue returns a copy of the value of the parent associated with the key in Val.

Instead of passing an optional parameter to a function, use the context value only for the request-scoped data of the staging process and API.

The supplied key must be comparable and should not be a string type or any other built-in type to avoid collisions between contexts used by the package. Withvalue users should define their own type of key. To avoid assigning an assignment to an interface {}, the context key often has a concrete type structure {}. In addition, the exported context-critical variable static type should be a pointer or an interface.

Take a look at the official example:

package mainimport (    "context"    "fmt")func main() {    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"))}

Reference connection

[1] Golang in context package interpretation
[2] Go language concurrency Model: using context

This article links: https://deepzz.com/post/golang-context-package-notes.html, participating in the comments»

--eof--

Posted in 2017-02-27 23:58:00, and added "go, context" tags.

This site uses the "Signature 4.0 International" Creative sharing agreement, reproduced please specify the author and the original website. More Instructions»

Reminder: This article was last updated 181 days ago, the information described in the article may have changed, please use it carefully.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.