Golang Context Detailed Introduction

Source: Internet
Author: User
Tags sprintf

Golang context

This article contains the context of the implementation of the analysis and use of the way, the analysis of some of the source code to explain the comparison, may be more boring, the reader can skip to read the use of the section directly.

  PS: The author in the spirit of open source sharing to write this article, if there is any error must leave a message, the author will be corrected in the first time, and jointly maintain a good open source ecology, thank you!!!

First, Introduction

The package name of the context that the author speaks of is: "Golang.org/x/net/context", I hope readers do not reference errors.

The context is described in Godoc as follows:

 Package context defines the context type, which carries deadlines, cancelation signals, and other request-scoped values a Cross API boundaries and between processes. As of Go 1.7 This is available in the standard library under the name context. Https://golang.org/pkg/context. Incoming requests to a server should create a context, and outgoing calls to servers should accept a context.  The chain of function calls between must propagate the Context, optionally replacing it with a modified copy created using Withdeadline, Withtimeout, Withcancel, or withvalue.programs, use contexts should follow these rules to keep INTERFAC  Es 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:func dosomething (CTX context. Context, arg arg) error {//...} Do not pass a nilContext, even if a function permits it. Pass context. TODO If you is unsure about which Context to use. Use context Values request-scoped data transits processes and APIs, not for passing optional parameters to F Unctions. The same Context is passed to functions running in different goroutines; Contexts is safe for simultaneous use by multiple goroutines. See Http://blog.golang.org/context For example code for a server that uses contexts.
View Code

  In view of the limited English proficiency of the author, there is no cross-reference translation here to avoid misleading readers. Its first sentence has introduced its role: a context type that runs through the API boundaries and processes, and can carry deadlines, cancel signals, and other information. Just like its Chinese translation: context. A lot of goroutines or processes run in parallel in an application service , and they are either subordinate, competitive, or mutually exclusive, and need to switch state and synchronize the data when different goroutines and processes interact. This is the feature that the context package is designed to support.

Second, the analysis

The interface definition for the context is as follows:

Each interface has a detailed comment, which is not repeated here. In the context of the source code has the following several structures implemented the context Interface:

A Context carries a deadline, a cancelation signal, and other values across//API boundaries. Context ' s methods is called by multiple Goroutines Simultaneously.type Context interface {//Deadline returns the T  IME when work done on behalf of this context//should is canceled.  Deadline returns Ok==false when no Deadline is//set.   Successive calls to Deadline return the same results. Deadline () (Deadline time.   Time, OK bool)//Done returns a channel that's closed when the work is done in behalf of this//context should is canceled.  Done could return nil if this context can//Never be canceled.   Successive calls to do return the same value.  Done () <-chan struct{}//ERR returns a Non-nil error value after do is closed.  ERR Returns//Canceled if the context was Canceled or deadlineexceeded if the//context ' s deadline passed.   No other values for ERR is defined.   After-done was closed, successive calls to ERR return the same value. ERR () Error//Value returns the value associated with this context for key, or nil//If no value was associated with key.   Successive calls to Value with//the same key returns the same result. Value (Key interface{}) interface{}}

2.1 Empty Context

An emptyctx is never canceled, have no values, and has no deadline. It is not//struct{}, since VARs of the this type must has distinct Addresses.type emptyctx intfunc (*emptyctx) Deadline () (d Eadline time. Time, OK bool) {    return}func (*emptyctx) Done () <-chan struct{} {    return Nil}func (*EMPTYCTX) ERR () error {
  
   return Nil}func (*EMPTYCTX) Value (Key interface{}) interface{} {    return Nil}func (e *emptyctx) string () string {    Switch e {case    background:        return "context. Background "Case    TODO:        return" context. TODO "    }    return" Unknown Empty Context "}
  

This is an empty CTX type, each return value is empty, it does not have any function, the main function is as the starting point of all the context type,context. The Background () function returns the context of this type:

var (    background = new (EMPTYCTX)    todo       = new (EMPTYCTX))//Background returns a Non-nil, empty Context. It is never canceled, with 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//reques Ts.func Background () Context {    return Background}

Empty context The role of the author is described below.

2.2 Cancle Context

A Cancelctx can be canceled. When canceled, it also cancels any children//that implement Canceler.type cancelctx struct {Context mu sync. Mutex//protects following fields do Chan struct{}//created lazily, closed by first cancel Call children map[canceler]struct{}//set to nil by the first cancel call err Error//set to        Non-nil by the first cancel Call}func (c *cancelctx) done () <-chan struct{} {c.mu.lock () if C.done = nil { C.done = Make (chan struct{})} D: = C.done c.mu.unlock () return D}func (c *cancelctx) ERR () error {C.MU . Lock () defer c.mu.unlock () return C.err}func (c *cancelctx) string () string {return FMT. Sprintf ("%v.withcancel", C.context)}//cancel closes C.done, cancels each of the C ' s children, and, if//removefromparent is t Rue, removes C from its parent ' s Children.func (c *cancelctx) cancel (removefromparent bool, err error) {if Err = = Nil {Panic ("Context:internal error:missing Cancel Error")} c.mu.lock () if c.err! = nil {c.mu.unlock () Retu RN//already canceled} C.err = Err if C.done = = Nil {C.done = Closedchan} else {Close (C.don        e)} for child: = range C.children {//note:acquiring the child's lock while holding parent ' s lock.  Child.cancel (False, err)} C.children = Nil C.mu.unlock () if removefromparent {removechild (C.context, c)}}

Member variables in the CANCELCTX:

' Done Chan struct{} ': The variable is returned when the done () function is called, which can be used to synchronize state between multiple goroutines;

' Children map[canceler]struct{} ': A context can be referenced by another context, the referenced context is parant, the reference context is children, and the variable contains all the children Context

' Context ': inherits all of the context's interfaces, but does not implement value () and deadline ();

The Cancel function is a protected function that cannot be called externally, and you can see that the done chain is closed when the function is executed, and that it invokes all the cancel functions of the children context. This is actually better understood, because the life cycle of the children context is dependent on the parant context. It also calls the removechild (C.context, c) function to dismiss the reference relationship to the Parant Context.

In the context. The cancel context is returned in the Withcancel (parent Context) function;

2.3 Timer Context

A timerctx carries a timer and a deadline. It embeds a cancelctx to//implement done and ERR. It implements cancel by stopping their timer then//delegating to CancelCtx.cancel.type timerctx struct {cancelctxtimer *tim E.timer//Under CancelCtx.mu.deadline time. Time}func (c *timerctx) Deadline () (Deadline time. Time, OK bool) {return c.deadline, True}func (c *timerctx) string () string {return FMT. Sprintf ("%v.withdeadline (%s [%s])", C.cancelctx.context, C.deadline, time. Until (C.deadline))}func (c *timerctx) cancel (removefromparent bool, err error) {C.cancelctx.cancel (false, Err) if removefromparent {//Remove this timerctx from its parent cancelctx ' s children.removechild (C.cancelctx.context, c)} C.mu.lock () if c.timer! = nil {c.timer.stop () C.timer = Nil}c.mu.unlock ()}

Member variables in the timer context:

' Cancelctx ': Timercontext inherits the Canel context type, which inherits all the member variables in the cancel type context;

' Timer ': A timer used to set time-outs;

' Dealine ': A time type used to record the time of death;

Cancel function: Overloads the Canel () function of the cancel Context above, which invokes RemoveChild (C.cancelctx.context, c) to release all children Context that relies on it, Then it will stop its timer and the time will end;

It implements string () and Deadline () but does not implement value (), overloading the Cancel context string () function;

In withdeadline (parent Context, Deadline time. Time) and Withtimeout (parent Context, timeout time. Duration) function, the timer context is returned;

2.4 Value Context  

A valuectx carries a key-value pair.  It implements Value for this key and//delegates all and calls to the embedded Context.type valuectx struct {contextkey, Val Interface{}}func (c *valuectx) string () string {return FMT. Sprintf ("%v.withvalue (% #v,% #v)", C.context, C.key, C.val)}func (c *valuectx) Value (Key interface{}) interface{} {if c.ke y = = key {return C.val}return C.context.value (key)}

Value Context member variable:

Context: It inherits all the interfaces of the context, but does not implement it, so it is necessary to use VALUECTX to assign the variable;

Key,val interface{}: Two variables form a key-value structure;

It implements the value () interface and can return the value corresponding to key.

The Withvalue (parent Context, Key, Val interface{}) function returns the value Context.

2.5 Summary

The four types of context are summarized below

Name Deadline Done Err Value Inherited
Empty + + + + Nil
Cancel - + + - Context
Timer + - - - Canel
Value - - - + Context

We can find that all three other types except empty do not fully implement the entire interface of the context, if a cancel context object is instantiated directly, but the context part is not assigned, when calling its value and the deadline interface crashes, The same is true for timer context and value. Readers must remember the above four types, so you can easily understand the following content.

Third, the use of the context

3.1 Context Common functions

  We mentioned a number of functions in the above introduction process:

Create a Cancel context
Func Withcancel (parent Context) (CTX context, cancel Cancelfunc)
Create a timer Contextfunc Withdeadline with deadline (parent Context, Deadline time. Time) (Context, Cancelfunc)
Create a timer with timeout Contextfunc withtimeout (parent Context, timeout time. Duration) (Context, Cancelfunc)
Create a value Contextfunc withvalue (parent context, key, Val interface{}) Context

These functions are often used in the context, and we do not parse all the functions here, just take the Withcancel function as an example:

Func Withcancel (parent Context) (CTX context, cancel Cancelfunc) {c: = Newcancelctx (parent) Propagatecancel (parent, & c) return &c, func () {C.cancel (True, Canceled)}}

Instantiate a cancel context object in the Newcancel function:

Newcancelctx returns an initialized Cancelctx.func Newcancelctx (parent Context) Cancelctx {return cancelctx{context:p Arent}}

Propagatecancel as noted in the note: Find the nearest parent context that can be canceled, place the child context in the parent's children queue, or open a goroutines to wait for a notification to exit the main chain if it cannot be found.

Propagatecancel arranges for canceled when parent Is.func Propagatecancel (parent Context, child Canceler) { If parent. Done () = = Nil {return//parent is never canceled}if p, OK: = Parentcancelctx (parent); OK {p.mu.lock () if p.err! = Nil {//parent has already been canceledchild.cancel (false, P.err)} else {if P.children = Nil {P.children = make (map[canceler]struct{})}p.children[child] = Struct{}{}}p.mu.unlock ()} else {go func () {select {Case & Lt;-parent. Done (): Child.cancel (False, parent.) ERR ()) Case <-child. Done ():}} ()}}

Parentcancelctx: Look up the reference along the Parant and trace it up until a cancelctx is found;

Parentcancelctx follows a chain of the parent references until it finds a//*cancelctx. This function understands what each of the concrete types in this//package represents its Parent.func parentcancelctx (pare NT Context) (*CANCELCTX, bool) {for   {      switch c: = parent. ( Type) {case      *cancelctx:         return C, True case      *timerctx:         return &c.cancelctx, True case      * Valuectx:         parent = c.context      default:         return nil, False      }   }

It also returns a function pointer, which is actually executing the Cancel function in Cancelctx.

In general, creating a new context is to mount a children context in the parant context, perhaps the incoming parent and the newly generated CTX will be attached to the same ctx, and may be added to the parent Contxt in the children queue. We want to compare the above four types of context, empty context and value context are not capable of mounting children, while the cancel context and timer context two types have mount Chidren 's ability.

But the problem is that when you create the cancel context you need to pass in a parent parameter, where does the parent come from? This is the function of the Func Background () context, which returns a context object as the starting point, and this backgroundctx is an empty context, which is empty The role of the context . Recall that the above introduction is not a reasonable construction?

3.2. Application example of context

Reference URL

[1] Https://godoc.org/golang.org/x/net/context

  

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.