Cancel coroutine execution using Context in Go
In Go language, goroutine is a lightweight thread that is very suitable for handling concurrent tasks. However, how to elegantly cancel a running coroutine is a common problem. This article will use a specific example to show how to use itcontext
Packages to cancel the execution of coroutines, especially dealing with cancellation issues in nested tasks.
Problem description
Suppose we have a long running task that contains an outer loop and an inner task. We need to be able to terminate the inner layer task immediately when the outer layer cycle receives the cancel signal. Here is a sample code:
package main import ( "context" "fmt" "time" ) // longRunningTask is a task that simulates long-running.func longRunningTask(ctx ) { for { select { case <-(): // Listen () to get the cancel signal ("The mission was cancelled:", ()) return // Exit after receiving the cancel signal default: currentTime := ().Format("2006-01-02 15:04:05") // Get and format the current time ("Task in progress... Current time: %s\n", currentTime) for { ("111") (1 * ) // } } } } func main() { // Create a context that can be cancelled ctx, cancel := (()) // Start a new goroutine to execute the task go longRunningTask(ctx) // Cancel the task after a period of simulation (3 * ) ("Cancel the task...") cancel() // Send a cancel signal // Wait for a while to allow the task to have time to process the cancel signal and exit (10 * ) }
In this example, when we cancel the task, the outer loop receives the cancel signal and exits, but the inner loop continues to run because we are not checking for the cancel signal in the inner loop.
Solution
To ensure that the inner task can also respond to the cancel signal, we need to check the () channel in the inner task as well. The following is the modified code:
package main import ( "context" "fmt" "time" ) // longRunningTask is a task that simulates long-running.func longRunningTask(ctx ) { for { select { case <-(): // Listen () to get the cancel signal ("The mission was cancelled:", ()) return // Exit after receiving the cancel signal default: currentTime := ().Format("2006-01-02 15:04:05") // Get and format the current time ("Task in progress... Current time: %s\n", currentTime) // Start inner-level tasks runInnerTask(ctx) } } } // runInnerTask is a task that simulates the long running of the inner layer.func runInnerTask(ctx ) { for { select { case <-(): // Inner tasks are also monitored () ("Inner task was cancelled:", ()) return // Exit after receiving the cancel signal default: ("111") (1 * ) } } } func main() { // Create a context that can be cancelled ctx, cancel := (()) // Start a new goroutine to execute the task go longRunningTask(ctx) // Cancel the task after a period of simulation (3 * ) ("Cancel the task...") cancel() // Send a cancel signal // Wait for a while to allow the task to have time to process the cancel signal and exit (10 * ) }
explain
Outer loop:
The outer loop uses the select statement to listen to the () channel. If a cancel signal is received, the task prints a message and exits.
Inner task:
Inner tasks also use the select statement to listen to the () channel. If a cancel signal is received, the inner layer task prints a message and exits.
In this way, we can ensure that the task responds to cancel signals and exits gracefully, whether in outer loops or inner tasks.
Summarize
In Go, it is very important to use the context package to manage the life cycle of a coroutine. By checking the () channel at every place where we need to respond to the cancel signal, we can ensure that the task can respond to the cancel signal in a timely manner and exit gracefully. This is essential for building robust and reliable concurrent applications.
This is the article about using Context to cancel coroutine execution in Go language. For more related content on Go Context to cancel coroutine execution, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!