Context context
Context emerged to solve the problem of coordinating and managing communication, timeouts and canceling operations between multiple goroutines in concurrent environments in large applications. It provides a standardized mechanism to pass request-related values between different parts of a program and can propagate and cancel these values throughout the call chain.
The main purpose of Context is:
- Pass the value of the request range: Through the Context, the request-related values can be passed in different function calls, such as the request ID, user authentication information, logger, etc. This avoids explicitly passing these values between functions, making the code clearer and more concise.
- Control concurrent operations: Through the cancel signal of the Context, the relevant goroutine can be notified to stop running and return, thereby achieving control of the concurrent operations. This is very useful for handling long-running operations or avoiding resource leaks.
- Set the deadline: Context allows setting the deadline for the operation, and the relevant operation will be automatically cancelled after this time. This is very useful for avoiding long waits or timeouts, and can improve system reliability and performance.
- Propagation and Inheritance: Context allows you to propagate and inherit request-range values and cancel signals throughout the call chain without explicitly passing them. This reduces duplicate operations in the code and ensures that all relevant goroutines receive the same context information.
In summary, Context emerged to provide a unified mechanism for managing concurrent operations, passing request-related values, and controlling the timeout and cancellation of operations. It simplifies the concurrent programming model and improves the readability, maintainability and testability of the code.
1. Context interface definition
type Context interface { Deadline() (deadline , ok bool) Done <-chan struct{} Err() error Value(key interface{}) interface{} }
-
Deadline() (deadline , ok bool)
:Method Function: The Deadline method returns the time when the work in this context should be cancelled. When no deadline is set, the Deadline method returns ok==false. Continuous calls to the Deadline method will return the same result:
-
deadline
: Indicates the deadline of the Context. If the deadline is not set or the deadline has expired, the return value of zero. Deadline method returns ok==false. -
ok
: Boolean value indicating whether the deadline exists. If there is a deadline,true
; otherwisefalse
。
-
-
Done() <-chan struct{}
:Method function: Return a read-only channel (
<-chan struct{}
), the channel is closed when the Context is cancelled or expired.Return value: Returns a read-only channel through which the cancel or expired signal of the Context can be received.
-
Err() error
:Method function: Returns the reason why the Context was cancelled (Error message).
Return value:
- If the Context has been cancelled, a non-empty error object is returned, describing the reason for the cancellation.
- If the Context has not been cancelled yet, or the reason for cancellation is unknown, return
nil
。
-
Value(key interface{}) interface{}
:Method function: Returns the value associated with the Context based on the given key.
parameter:
key
Key indicating the value to be retrieved.Return value:
- If the value associated with the Context exists, the value associated with the given key is returned (type of
interface{}
)。 - If there is no value associated with the given key, return
nil
。
- If the value associated with the Context exists, the value associated with the given key is returned (type of
2. Error settings
// Canceled is the error returned by when the context is canceled. var Canceled = ("context canceled") // DeadlineExceeded is the error returned by when the context's // deadline passes. var DeadlineExceeded error = deadlineExceededError{} type deadlineExceededError struct{} func (deadlineExceededError) Error() string { return "context deadline exceeded" } func (deadlineExceededError) Timeout() bool { return true } func (deadlineExceededError) Temporary() bool { return true }
In the above code, two predefined error variables are defined: Canceled and DeadlineExceeded, which represent context cancellation and timeout.
Canceled
It is when the context is cancelledThe error returned. It's a
Created error, indicating that the context has been cancelled.
DeadlineExceeded
is when the deadline of the context has passedThe error returned. It is a custom error type
deadlineExceededError
Examples of . This type has been implementederror
Interface method.
-
Error()
The method returns an error string indicating that the context deadline has expired, i.e. "context deadline exceeded". -
Timeout()
Method returntrue
, indicating that the error was caused by a timeout. -
Temporary()
Method returntrue
, indicating that the error is temporary.
3. emptyCtx
type emptyCtx int func (*emptyCtx) Deadline() (deadline , ok bool) { return } func (*emptyCtx) Done() <-chan struct{} { return nil } func (*emptyCtx) Err() error { return nil } func (*emptyCtx) Value(key any) any { return nil } func (e *emptyCtx) String() string { switch e { case background: return "" case todo: return "" } return "unknown empty Context" }
emptyCtx
is an empty context type. It has the following characteristics:
- Never cancelled:
emptyCtx
is a non-cancellable context, i.e. no action will cause it to be cancelled. - No value:
emptyCtx
No value associated with it is stored. - No deadline:
emptyCtx
No cutoff time is set, that is, there is no limit on the cutoff time.
emptyCtx
The type is notstruct{}
, because such variables must have different addresses. In fact,emptyCtx
is an internal type that represents a special empty context.
This empty context is used in some special cases, such as as the root context or the default context, which can be used instead without explicitly providing the context. Due to its non-cancellable, no value, and deadline nature, it provides an empty placeholder context instance in some scenarios.
4. Two emptyCtx
var ( background = new(emptyCtx) todo = new(emptyCtx) ) func Background() Context { return background } func TODO() Context { return todo }
4.1. Background
Background
The function returns a non-empty empty context. It has the following characteristics:
- Never cancelled:
Background
A context is a non-cancellable context, i.e. no action will cause it to be cancelled. - No value:
Background
The context does not store any value associated with it. - No deadline:
Background
The context does not set any deadline, i.e. there is no limit on the deadline.
Background
A context is a commonly used context instance, commonly used for main functions, initialization procedures, tests, and top-level contexts as incoming requests. It provides an empty placeholder context for scenarios where no specific context is required. Due to its unabolition, no value and deadline characteristics,Background
Contexts are often used when starting programs, performing initialization operations, and processing inbound requests.
4.2. TODO
TODO
The function returns a non-empty empty context. In code, when it is not clear which context to use or the context is not available yet (because the surrounding functions have not been extended to accept context parameters), you should use。
TODO
A context is a temporary placeholder context that indicates a situation where the context has not been determined or is not available. It can be used as a temporary solution in the encoding process before the code is further refined. You can use it when you need to pass the context but you have not yet selected which context to use yetTODO
Come and take up the place, and replace it according to the specific situation.
5. CancleFun
// A CancelFunc tells an operation to abandon its work. // A CancelFunc does not wait for the work to stop. // A CancelFunc may be called by multiple goroutines simultaneously. // After the first call, subsequent calls to a CancelFunc do nothing. type CancelFunc func()
CancelFunc
is a function type that notifies an operation to abandon its work.CancelFunc
It will not wait for the work to stop, it just sends a cancel signal.CancelFunc
Can be called simultaneously by multiple goroutines. After the first call,CancelFunc
The subsequent calls will not have any effect.
When an operation needs to be canceled, it can be calledCancelFunc
function to notify the relevant operation to stop working. This function type can be used with、
、
Used together with functions that return a
CancelFunc
。
It should be noted that the callCancelFunc
It just sends a cancel signal to the operation. Whether the specific operation really stops depends on the implementation of the operation itself.CancelFunc
The call does not block, it will return immediately.
In useCancelFunc
When , you should pay attention to the concurrent call situation, because it can be called by multiple goroutines at the same time. Ensure cancellation operations are handled correctly in concurrency to avoid potential race conditions and problems.
6. cancleCtx
type cancelCtx struct { Context mu // protects following fields done // of 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 cause error // set to non-nil by the first cancel call }
cancelCtx
yescontext
A structure type defined in the package implementsContext
interface. It is a context type based on the cancel mechanism and is used to represent a context that can be canceled.
Below iscancelCtx
Detailed introduction to structure:
-
Context
: Embed field, representcancelCtx
The structure has been implementedContext
Interface, can be used as context objects. -
mu
:A mutex of type that protects concurrent access to the following fields.
-
done
:Atomic value of type, used to store a
chan struct{}
, the channel is closed when the call is first canceled. This field is created lazy, i.e. before the first cancellation of the callnil
. It is used to notify that the relevant goroutine context has been cancelled. -
children
:map[canceler]struct{}
Field of type that stores the subcontext associated with that context (byWithCancel
、WithDeadline
orWithTimeout
create). The subcontext is stored in the map as a key, and the corresponding value is an empty structure. After the first cancellation of the call, the field is set tonil
。 -
err
:error
A field of type that stores the cancel error of the context. After the first cancellation of the call, the field will be set to nonnil
Error value of . -
cause
:error
Field of type, used to store the context's cancellation reason. After the first cancellation of the call, the field will be set to nonnil
Error value of .
cancelCtx
Structures are used to implement context cancellation mechanisms. When calledcancel
When the method is closeddone
The channel to notify that the relevant goroutine context has been cancelled. At the same time, it will be seterr
The field is a cancel error and records the cancellation reason (if provided). Subcontexts will also be cancelled, i.e. theircancel
The method will be called and will itself fromchildren
Delete in the map.
This cancel mechanism-based context type can be used to pass a cancel signal between multiple goroutines, so that the related operations can be terminated in time if needed.
7. WithCancel
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := withCancel(parent) return c, func() { (true, Canceled, nil) } }
WithCancel
The main features and steps of the function:
- Return a copy based on the parent context and create a new one
Done
aisle. - When the call returns
cancel
Function or parent contextDone
When the channel is closed, the context returnedDone
The channel will also be closed. - Call
cancel
Functions release context-related resources, so they should be called as soon as possible after the operation is completed. - use
WithCancel
The created context can be manually cancelled and ensures timely release of resources.
func Cancel() { // Create a context with cancel function ctx, cancel := (()) // Start a goroutine to perform timing tasks go func() { for { select { case <-(): ("Timed task cancelled") return default: // Simulate the work of timing tasks ("Execute timing tasks...") (1 * ) } } }() // Simulate and wait for a while before canceling the timing task (5 * ) cancel() // Wait for a while to observe the status of the task (2 * ) }
wangyufan@wangcomputerair MINGW64 /d/goworkplace/src//context (master)
$ go run .
Perform timing tasks...
Perform timing tasks...
Perform timing tasks...
Perform timing tasks...
Perform timing tasks...
The scheduled task was canceled
In this example, we create a context with a cancel function (ctx
) and the corresponding cancel function (cancel
). Then, we initiate a goroutine to execute the timing task, outputting "Execute timing task..." every second. In the main function, we waited for 5 seconds before callingcancel
function, send a cancel signal. Finally, we wait for 2 seconds to observe the status of the task.
By running this example, you can observe that after canceling the signal, the timing task will stop executing immediately, and the output "timing task is cancelled", without continuing to execute the remaining timing tasks. This shows how to use()
Apparent examples of canceling tasks
8. WithDeadline
func WithDeadline(parent Context, d ) (Context, CancelFunc){}
WithDeadline
The function returns a parent contextparent
and set a deadlined
. The returned context object has a newDone
channel, when the deadline reaches or the parent contextDone
When the channel is closed (whichever occurs first), theDone
The channel will be closed.
Cancel the context frees the resources associated with it, so the code should be called as soon as possible after the operation performed with that context is completed.cancel
function.
WithDeadline
The function is to create a context with a deadline. This context can be used to control the execution time of the operation, and once the deadline has reached, the related operation can be cancelled or aborted.
It should be noted that the deadline is an absolute time and can be used()
CombinedTo specify a deadline relative to the current time.
WithDeadline
The main features and steps of the function are as follows:
- Return a copy based on the parent context and set the deadline to
d
。 - Create a new
Done
channel, when the deadline reaches or the parent contextDone
When the channel is closed,Done
The channel will be closed. - Call
cancel
Functions release context-related resources, so they should be called as soon as possible after the operation is completed. - use
WithDeadline
The created context can control the execution time of the operation and cancel or abort the related operation when the deadline reaches.
func Dead() { ctx, cancel := ((), ().Add(5*)) // Start a goroutine to perform tasks go func() { for { select { case <-(): ("The mission was cancelled:", ()) return default: // Simulate tasks ("Execute tasks...") (1 * ) } } }() // Wait for a while to observe the status of the task (8 * ) // Cancel the task cancel() // Wait for a while to observe the status of the task (2 * ) }
wangyufan@wangcomputerair MINGW64 /d/goworkplace/src//context (master)
$ go run .
Execute tasks...
Execute tasks...
Execute tasks...
Execute tasks...
Execute tasks...
Task cancelled: context deadline exceeded
In this example, we use()
Created a context with a deadline (ctx
) and the corresponding cancel function (cancel
). By calling().Add(5*)
, we set the deadline to the current time after 5 seconds. Then, we start a goroutine to execute the task, outputting "Execute task..." every second. In the main function, we waited for 8 seconds, exceeded the deadline, and then calledcancel
Function cancels the task. Finally, we wait for 2 seconds to observe the status of the task.
By running this example, you can observe that after the deadline reaches, the task will be stopped immediately and the output "Task cancelled". This shows how to use()
An example of setting a deadline and canceling a task.
9. WithTimeOut
func WithTimeout(parent Context, timeout ) (Context, CancelFunc) { return WithDeadline(parent, ().Add(timeout)) }
WithTimeout
The function iscontext
A helper function in the package that is based on the parent contextparent
and timeouttimeout
Create a new context and return that context and the corresponding cancel function.
The internal implementation of the function is calledWithDeadline
Function, add the current time to the timeout time to get the deadline, and then call the deadline as a parameterWithDeadline
, return the corresponding context and cancel function.
in short,WithTimeout
The function uses the timeout time relative to the current time to create a context with a deadline. The timeout time can be a duration () object, indicating a period of time starting from the current time.
useWithTimeout
Functions can conveniently create a context with timeout control to ensure that relevant operations can be cancelled or aborted after the timeout time has arrived.
It should be noted that the timeout should be a non-negative value. If the timeout is zero or negative, it means that the timeout is immediately, that is, the operation will be cancelled immediately.
// TimeOut the function that will be testing the func TimeOut() { // Set a context with a timeout of 5 seconds ctx, cancel := ((), 5*) // Start a goroutine to perform tasks go func() { for { select { case <-(): ("The mission was cancelled:", ()) return default: // Simulate tasks ("Execute tasks...") (1 * ) } } }() // Wait for a while to observe the status of the task (8 * ) // Cancel the task cancel() // Wait for a while to observe the status of the task (2 * ) }
wangyufan@wangcomputerair MINGW64 /d/goworkplace/src//context (master)
$ go run .
Execute tasks...
Execute tasks...
Execute tasks...
Execute tasks...
Execute tasks...
Task cancelled: context deadline exceeded
In this example, we use()
Created a context with a timeout time (ctx
) and the corresponding cancel function (cancel
). By setting the timeout to 5 seconds (5*
), we limit the execution time of the task. Then, we start a goroutine to execute the task, outputting "Execute task..." every second. In the main function, we waited for 8 seconds, exceeded the timeout, and then calledcancel
Function cancels the task. Finally, we wait for 2 seconds to observe the status of the task.
By running this example, you can observe that after the timeout time arrives, the task will stop executing immediately and output "task cancelled". This shows how to use()
An example of setting a timeout time and canceling a task.
10. WithValue
func WithValue(parent Context, key, val any) Context { if parent == nil { panic("cannot create context from nil parent") } if key == nil { panic("nil key") } if !(key).Comparable() { panic("key is not comparable") } return &valueCtx{parent, key, val} }
WithValue
The function iscontext
A helper function in the package for parent contextparent
Create a new context and set key-value pairs(key, val)
Stored in a new context. The function returns a new context object.
The function first performs some parameter verification to ensureparent
Not empty,key
Not fornil
,andkey
is comparable. In Go, comparable types are what you can use==
The type of operators that compare.
Then, the function creates avalueCtx
structure, and parent context,key
andval
Stored in this structure.valueCtx
yescontext
An internal type defined in the package that stores the key-value pair information of the context.
Finally, the function returns the newly createdvalueCtx
object, it implementsContext
interface.
By usingWithValue
Functions that store and pass request-related data in the context, which can be passed across API boundaries and process boundaries. It should be noted thatWithValue
Functions are suitable for passing request-range data and should not be used to pass optional function parameters.
func Test() { // Create a parent context parent := () // Create a child context with user identity information using WithValue user := User{ID: 123, Name: "Alice"} ctx := (parent, "user", user) // Get user identity information in different functions processRequest(ctx) } // processRequest a function that get information from ctx func processRequest(ctx ) { // Get user identity information from the context user, ok := ("user").(User) if !ok { ("User ID information cannot be obtained") return } // Use user identity information to perform request processing ("Processing request, user ID: %d, user name: %s\n", , ) // Call other functions to pass the context otherFunction(ctx) } // otherFunction another function that get information form ctx func otherFunction(ctx ) { // Get user identity information from the context user, ok := ("user").(User) if !ok { ("User ID information cannot be obtained") return } // Use user identity information to perform other operations ("Perform other actions, user ID: %d, user name: %s\n", , ) }
wangyufan@wangcomputerair MINGW64 /d/goworkplace/src//context (master)
$ go run .
Process the request, user ID: 123, user name: Alice
Perform other operations, user ID: 123, user name: Alice
In this example, we first create a parent contextparent
. Then, we use()
Configure user identity informationUser{ID: 123, Name: "Alice"}
Associated with the context, create a child context with user identity informationctx
. Next, we callprocessRequest(ctx)
Passes child context to the function that handles the request.
existprocessRequest
In the function, we obtain user identity information from the context and use this information to perform request processing. Then, we callotherFunction(ctx)
Pass the context to another function.
existotherFunction
In the function, we also obtain user identity information from the context and use this information to perform other operations.
By running this example, you can observe that user identity information was successfully obtained in different functions and used the information to perform corresponding processing and operations. This shows how to use()
Associate user identity information with context and pass and get this information in different functions.
The above is the detailed content of the Context in go language that allows you to understand the details of the Context. For more information about go Context, please follow my other related articles!