使用Go语言中的Context取消协程执行的操作代码

 更新时间:2024年11月29日 11:08:23   作者:软件架构师笔记  
在 Go 语言中,协程(goroutine)是一种轻量级的线程,非常适合处理并发任务,然而,如何优雅地取消正在运行的协程是一个常见的问题,本文将通过一个具体的例子来展示如何使用 context 包来取消协程的执行,需要的朋友可以参考下

使用 Go 语言中的 Context 取消协程执行

在 Go 语言中,协程(goroutine)是一种轻量级的线程,非常适合处理并发任务。然而,如何优雅地取消正在运行的协程是一个常见的问题。本文将通过一个具体的例子来展示如何使用 context 包来取消协程的执行,特别是处理嵌套任务中的取消问题。

问题描述

假设我们有一个长时间运行的任务,该任务包含一个外层循环和一个内层任务。我们需要在外层循环接收到取消信号时,能够立即终止内层任务。以下是一个示例代码:

package main

import (
	"context"
	"fmt"
	"time"
)

// longRunningTask 是一个模拟长时间运行的任务。
func longRunningTask(ctx context.Context) {
	for {
		select {
		case <-ctx.Done(): // 监听 ctx.Done() 以获取取消信号
			fmt.Println("任务被取消:", ctx.Err())
			return // 接收到取消信号后退出
		default:
			currentTime := time.Now().Format("2006-01-02 15:04:05") // 获取并格式化当前时间
			fmt.Printf("任务进行中... 当前时间:%s\n", currentTime)
			for {
				fmt.Printf("111")
				time.Sleep(1 * time.Second) //
			}
		}
	}
}

func main() {
	// 创建一个可以取消的 context
	ctx, cancel := context.WithCancel(context.Background())

	// 启动一个新的 goroutine 执行任务
	go longRunningTask(ctx)

	// 模拟一段时间后取消任务
	time.Sleep(3 * time.Second)
	fmt.Println("取消任务...")
	cancel() // 发送取消信号

	// 等待一段时间让任务有时间处理取消信号并退出
	time.Sleep(10 * time.Second)
}

在这个示例中,当我们取消任务时,外层循环会接收到取消信号并退出,但内层循环会继续运行,因为我们没有在内层循环中检查取消信号。

解决方案

为了确保内层任务也能响应取消信号,我们需要在内层任务中也检查 ctx.Done() 通道。以下是修改后的代码:

package main

import (
	"context"
	"fmt"
	"time"
)

// longRunningTask 是一个模拟长时间运行的任务。
func longRunningTask(ctx context.Context) {
	for {
		select {
		case <-ctx.Done(): // 监听 ctx.Done() 以获取取消信号
			fmt.Println("任务被取消:", ctx.Err())
			return // 接收到取消信号后退出
		default:
			currentTime := time.Now().Format("2006-01-02 15:04:05") // 获取并格式化当前时间
			fmt.Printf("任务进行中... 当前时间:%s\n", currentTime)
			// 启动内层任务
			runInnerTask(ctx)
		}
	}
}

// runInnerTask 是一个模拟内层长时间运行的任务。
func runInnerTask(ctx context.Context) {
	for {
		select {
		case <-ctx.Done(): // 内层任务也监听 ctx.Done()
			fmt.Println("内层任务被取消:", ctx.Err())
			return // 接收到取消信号后退出
		default:
			fmt.Printf("111")
			time.Sleep(1 * time.Second)
		}
	}
}

func main() {
	// 创建一个可以取消的 context
	ctx, cancel := context.WithCancel(context.Background())

	// 启动一个新的 goroutine 执行任务
	go longRunningTask(ctx)

	// 模拟一段时间后取消任务
	time.Sleep(3 * time.Second)
	fmt.Println("取消任务...")
	cancel() // 发送取消信号

	// 等待一段时间让任务有时间处理取消信号并退出
	time.Sleep(10 * time.Second)
}

解释

外层循环:

外层循环使用 select 语句来监听 ctx.Done() 通道。如果接收到取消信号,任务会打印一条消息并退出。

内层任务:

内层任务也使用 select 语句来监听 ctx.Done() 通道。如果接收到取消信号,内层任务会打印一条消息并退出。

通过这种方式,我们可以确保无论是在外层循环还是内层任务中,任务都能响应取消信号并优雅地退出。

总结

在 Go 语言中,使用 context 包来管理协程的生命周期是非常重要的。通过在每个需要响应取消信号的地方检查 ctx.Done() 通道,我们可以确保任务能够及时响应取消信号并优雅地退出。这对于构建健壮和可靠的并发应用程序至关重要。

到此这篇关于使用Go语言中的Context取消协程执行的操作代码的文章就介绍到这了,更多相关Go Context取消协程执行内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于Go 空结构体的 3 种使用场景

    关于Go 空结构体的 3 种使用场景

    在今天这篇文章要给大家介绍得是Go 语言中几种常见类型的宽度,并且基于开头的问题 ”空结构体“ 进行了剖析,需要的朋友可以参考一下,希望对你有所帮助
    2021-10-10
  • Go语言中利用http发起Get和Post请求的方法示例

    Go语言中利用http发起Get和Post请求的方法示例

    这篇文章主要给大家介绍了关于Go语言中利用http发起Get和Post请求的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-11-11
  • Golang 如何限制木马图片上传服务器的实例

    Golang 如何限制木马图片上传服务器的实例

    本文主要介绍了Golang 如何限制木马图片上传服务器的实例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • windows安装部署go超详细实战记录(实测有用!)

    windows安装部署go超详细实战记录(实测有用!)

    Golang语言在近年来因为其高性能、编译速度快、开发成本低等特点逐渐得到大家的青睐,这篇文章主要给大家介绍了关于windows安装部署go超详细实战的相关资料,需要的朋友可以参考下
    2023-02-02
  • Go基本数据类型的具体使用

    Go基本数据类型的具体使用

    本文主要介绍了Go的基本数据类型,包括布尔类型、整数类型、浮点数类型、复数类型、字符串类型,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • Go defer 原理和源码剖析(推荐)

    Go defer 原理和源码剖析(推荐)

    这篇文章主要介绍了Go defer 原理和源码剖析,需要的朋友可以参考下
    2021-11-11
  • Golang之sync.Pool对象池对象重用机制总结

    Golang之sync.Pool对象池对象重用机制总结

    这篇文章主要对Golang的sync.Pool对象池对象重用机制做了一个总结,文中有相关的代码示例和图解,具有一定的参考价值,需要的朋友可以参考下
    2023-07-07
  • Golang Gin框架中间件的用法详解

    Golang Gin框架中间件的用法详解

    中间件是Gin框架中的一个核心概念,它允许开发者在处理HTTP请求的过程中插入自定义的钩子函数,从而实现诸如日志记录、身份验证、权限控制等公共逻辑,本文将结合实际案例,详细讲解Gin框架中间件的用法
    2024-10-10
  • Go语言常用字符串处理方法实例汇总

    Go语言常用字符串处理方法实例汇总

    这篇文章主要介绍了Go语言常用字符串处理方法,实例汇总了Go语言中常见的各种字符串处理技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • Go语言中的逃逸分析究竟是什么?

    Go语言中的逃逸分析究竟是什么?

    这篇文章主要介绍了Go语言中的逃逸,套哟究竟是什么呢?通俗来讲,当一个对象的指针被多个方法或线程引用时,我们称这个指针发生了“逃逸”。下面文章将详细介绍Go语言中的逃逸,需要的朋友可以参考一下
    2021-09-09

最新评论