SoFunction
Updated on 2025-03-03

A article allows you to understand the Context of Go language

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, returnnil
  • Value(key interface{}) interface{}

    Method function: Returns the value associated with the Context based on the given key.

    parameter:keyKey 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 ofinterface{})。
    • If there is no value associated with the given key, returnnil

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.

CanceledIt is when the context is cancelledThe error returned. It's aCreated error, indicating that the context has been cancelled.

DeadlineExceededis when the deadline of the context has passedThe error returned. It is a custom error typedeadlineExceededErrorExamples of . This type has been implementederrorInterface 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"
 }

emptyCtxis an empty context type. It has the following characteristics:

  • Never cancelled:emptyCtxis a non-cancellable context, i.e. no action will cause it to be cancelled.
  • No value:emptyCtxNo value associated with it is stored.
  • No deadline:emptyCtxNo cutoff time is set, that is, there is no limit on the cutoff time.

emptyCtxThe type is notstruct{}, because such variables must have different addresses. In fact,emptyCtxis 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

BackgroundThe function returns a non-empty empty context. It has the following characteristics:

  • Never cancelled:BackgroundA context is a non-cancellable context, i.e. no action will cause it to be cancelled.
  • No value:BackgroundThe context does not store any value associated with it.
  • No deadline:BackgroundThe context does not set any deadline, i.e. there is no limit on the deadline.

BackgroundA 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,BackgroundContexts are often used when starting programs, performing initialization operations, and processing inbound requests.

4.2. TODO

TODOThe 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

TODOA 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 yetTODOCome 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()

CancelFuncis a function type that notifies an operation to abandon its work.CancelFuncIt will not wait for the work to stop, it just sends a cancel signal.CancelFuncCan be called simultaneously by multiple goroutines. After the first call,CancelFuncThe subsequent calls will not have any effect.

When an operation needs to be canceled, it can be calledCancelFuncfunction to notify the relevant operation to stop working. This function type can be used withUsed together with functions that return aCancelFunc

It should be noted that the callCancelFuncIt just sends a cancel signal to the operation. Whether the specific operation really stops depends on the implementation of the operation itself.CancelFuncThe call does not block, it will return immediately.

In useCancelFuncWhen , 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
 }

cancelCtxyescontextA structure type defined in the package implementsContextinterface. It is a context type based on the cancel mechanism and is used to represent a context that can be canceled.

Below iscancelCtxDetailed introduction to structure:

  • Context: Embed field, representcancelCtxThe structure has been implementedContextInterface, can be used as context objects.
  • muA mutex of type that protects concurrent access to the following fields.
  • doneAtomic value of type, used to store achan 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.
  • childrenmap[canceler]struct{}Field of type that stores the subcontext associated with that context (byWithCancelWithDeadlineorWithTimeoutcreate). 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
  • errerrorA field of type that stores the cancel error of the context. After the first cancellation of the call, the field will be set to nonnilError value of .
  • causeerrorField of type, used to store the context's cancellation reason. After the first cancellation of the call, the field will be set to nonnilError value of .

cancelCtxStructures are used to implement context cancellation mechanisms. When calledcancelWhen the method is closeddoneThe channel to notify that the relevant goroutine context has been cancelled. At the same time, it will be seterrThe field is a cancel error and records the cancellation reason (if provided). Subcontexts will also be cancelled, i.e. theircancelThe method will be called and will itself fromchildrenDelete 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) }
 }

WithCancelThe main features and steps of the function:

  • Return a copy based on the parent context and create a new oneDoneaisle.
  • When the call returnscancelFunction or parent contextDoneWhen the channel is closed, the context returnedDoneThe channel will also be closed.
  • CallcancelFunctions release context-related resources, so they should be called as soon as possible after the operation is completed.
  • useWithCancelThe 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 &lt;-():
                 ("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 callingcancelfunction, 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){}

WithDeadlineThe function returns a parent contextparentand set a deadlined. The returned context object has a newDonechannel, when the deadline reaches or the parent contextDoneWhen the channel is closed (whichever occurs first), theDoneThe 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.cancelfunction.

WithDeadlineThe 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.

WithDeadlineThe main features and steps of the function are as follows:

  • Return a copy based on the parent context and set the deadline tod
  • Create a newDonechannel, when the deadline reaches or the parent contextDoneWhen the channel is closed,DoneThe channel will be closed.
  • CallcancelFunctions release context-related resources, so they should be called as soon as possible after the operation is completed.
  • useWithDeadlineThe 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 &lt;-():
                 ("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 calledcancelFunction 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))
 }

WithTimeoutThe function iscontextA helper function in the package that is based on the parent contextparentand timeouttimeoutCreate a new context and return that context and the corresponding cancel function.

The internal implementation of the function is calledWithDeadlineFunction, 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,WithTimeoutThe 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.

useWithTimeoutFunctions 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 &lt;-():
                 ("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 calledcancelFunction 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}
 }

WithValueThe function iscontextA helper function in the package for parent contextparentCreate 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 ensureparentNot empty,keyNot fornil,andkeyis comparable. In Go, comparable types are what you can use==The type of operators that compare.

Then, the function creates avalueCtxstructure, and parent context,keyandvalStored in this structure.valueCtxyescontextAn internal type defined in the package that stores the key-value pair information of the context.

Finally, the function returns the newly createdvalueCtxobject, it implementsContextinterface.

By usingWithValueFunctions that store and pass request-related data in the context, which can be passed across API boundaries and process boundaries. It should be noted thatWithValueFunctions 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.

existprocessRequestIn 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.

existotherFunctionIn 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!