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.7
and 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 vet
The 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.
- 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 ... }
- Do not pass in the Context even if the function allows it
nil
. If you do not know which Context to use context.TODO()
.
- 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
- 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.