Context of Golang concurrency model

Source: Internet
Author: User
Tags comparable

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 is safe for simultaneousUseby multiple//Goroutines.TypeContextinterface {//DoneReturns a channel thatis closedWhen thisContextis canceled//or times out. Done () <-chanstruct{}//ERR indicates why thiscontext was canceled, after the Done Channel//is closed. ERR () error//Deadline returns the time when this Context would be Canceled, if any. Deadline () (Deadline time. Time, OK bool)//value returns the  Value associated with key or Nil Span class= "Hljs-keyword" >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

FuncBackground()ContextFuncTodo()Contextfunc withcancelcontext, 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.

   229FuncWithcancel(Parent Context) (CTXContext, CancelCancelfunc) {230c: = Newcancelctx (parent)231 Propagatecancel (Parent, &C232Return &Cfunc () {c.cancel (true, canceled)} 233}  234 235 //Newcancelctx returns an initialized cancelctx. 236 func  Newcancelctx237 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")FuncMain() {Gen generates integers in a separate goroutine andSends them to the returned channel.The callers of Gen need to cancel the context onceThey is done consuming generated integers not to leakThe internal goroutine started by Gen Gen: =Func(CTX context.) Context) <-Chanint {DST: =MakeChanint) 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) 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), Span class= "Hljs-number" >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:

PackageMainImport ("Context ""fmt "" time ")  Func main () {d: = Time. Now (). add (* time.millisecond) ctx, Cancel: = context. withdeadline (context. Background (), D)//Even though ctx'll be a expired, it is good the practice to call its//cancelation function in any case. Failure to does so is 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 //sh Ould abandon its, 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

   454func withvalue interface{}) context {454 if key = = nil {455 panic (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< Span class= "Hljs-params" (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] https://segmentfault.com/a/1190000006744213
[2] http://www.01happy.com/golang-context-reading/

My blog will soon be settled in "cloud habitat community", inviting technical colleagues to join together.

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.