cancel()

cancel() 取消的是上下文(context)本身,而不是正在执行的协程。
因此,协程的取消是通过 context 的取消信号来间接实现的。
具体地,协程会在收到 context 的取消信号后自行决定是否退出。

如何使用 cancel() 取消协程?

协程通常会通过检查 context 的状态来判断是否继续执行,cancel() 是通过取消 context 来通知协程停止工作。
以下是如何通过 contextcancel() 来控制协程的取消:

示例:

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)
}

代码解释:

  1. context.WithCancel(context.Background()):创建一个可以手动取消的 context
  2. cancel():当我们调用 cancel() 时,ctx.Done() 会收到取消信号。所有使用这个 ctx 的协程都可以通过 ctx.Done() 来接收取消信号并决定退出。
  3. 协程中使用 select 监听 ctx.Done(),一旦 context 被取消,协程会停止执行。

cancel() 如何工作:

  • cancel() 是用来通知与 context 相关的操作应该停止。这通常发生在请求超时、手动取消或父上下文取消时。
  • cancel() 会触发上下文的 Done() 通道,所有监听这个上下文的协程都可以在 Done() 通道中接收到信号,从而安全地停止自己的执行。

总结:

  • 取消协程的操作:是通过取消 context 来间接影响协程。cancel() 取消 context,然后协程在收到取消信号后执行相应的退出逻辑。
  • 协程通过监听 context.Done() 来判断是否需要退出,而不是通过直接调用 cancel() 来停止协程。
posted @ 2024-11-24 11:27  牛马chen  阅读(5)  评论(0编辑  收藏  举报