cancel()
cancel() 取消的是上下文(context)本身,而不是正在执行的协程。
因此,协程的取消是通过 context 的取消信号来间接实现的。
具体地,协程会在收到 context 的取消信号后自行决定是否退出。
如何使用 cancel() 取消协程?
协程通常会通过检查 context 的状态来判断是否继续执行,cancel() 是通过取消 context 来通知协程停止工作。
以下是如何通过 context 和 cancel() 来控制协程的取消:
示例:
package main
import (
"context"
"fmt"
"time"
)
func main() {
// 创建一个可取消的上下文
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // 确保在 main 函数退出时调用 cancel,取消所有相关的协程
// 启动一个新的协程,接收 ctx 来监听取消信号
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
// 当 ctx 被取消时,协程退出
fmt.Println("Task cancelled:", ctx.Err())
return
default:
// 继续执行任务
fmt.Println("Task is running...")
time.Sleep(1 * time.Second)
}
}
}(ctx)
// 主线程等一段时间后取消 ctx
time.Sleep(3 * time.Second)
cancel() // 调用 cancel() 来取消上下文
// 让协程有时间打印取消的消息
time.Sleep(1 * time.Second)
}
代码解释:
context.WithCancel(context.Background()):创建一个可以手动取消的context。cancel():当我们调用cancel()时,ctx.Done()会收到取消信号。所有使用这个ctx的协程都可以通过ctx.Done()来接收取消信号并决定退出。- 协程中使用
select监听ctx.Done(),一旦context被取消,协程会停止执行。
cancel() 如何工作:
cancel()是用来通知与context相关的操作应该停止。这通常发生在请求超时、手动取消或父上下文取消时。cancel()会触发上下文的Done()通道,所有监听这个上下文的协程都可以在Done()通道中接收到信号,从而安全地停止自己的执行。
总结:
- 取消协程的操作:是通过取消
context来间接影响协程。cancel()取消context,然后协程在收到取消信号后执行相应的退出逻辑。 - 协程通过监听
context.Done()来判断是否需要退出,而不是通过直接调用cancel()来停止协程。

浙公网安备 33010602011771号