golang中context详解

这篇具有很好参考价值的文章主要介绍了golang中context详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

编码中遇到上下文信息传递,并发信息取消等,记录下在go语言中context包的使用。


context 介绍

在Go语言中,context包提供了一种在程序中传递截止日期、取消信号、请求范围数据和其他元数据的方式。context包的核心类型是Context接口,它定义了在执行上下文中传递的方法。Context接口的主要方法包括Deadline、Done、Err、Value等。

关键概念和使用方式

  1. Background: context.Background()函数返回一个空的Context,通常作为整个应用的顶层上下文,用于传递全局的信息。

  2. WithCancel: context.WithCancel函数创建一个带有取消信号的Context。当调用返回的cancel函数时,与该Context相关联的所有操作都会被取消。

    ctx, cancel := context.WithCancel(context.Background())
    defer cancel() // 在不再需要时调用cancel
    
  3. WithTimeout和WithDeadline: context.WithTimeoutcontext.WithDeadline函数创建带有截止日期的ContextWithTimeout设置相对于当前时间的截止日期,而WithDeadline设置绝对时间的截止日期。

    ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
    defer cancel() // 在不再需要时调用cancel
    
  4. WithValue: context.WithValue函数可以在Context中存储键值对,用于传递请求范围的数据。但要注意,过度使用WithValue可能导致上下文变得复杂,应慎重使用。

    ctx := context.WithValue(context.Background(), key, value)
    
  5. Done和Err: Done通道会在上下文被取消或达到截止日期时关闭。Err方法返回取消的原因,通常是context.Canceledcontext.DeadlineExceeded

    select {
    case <-ctx.Done():
        // 上下文被取消
        fmt.Println("Context canceled:", ctx.Err())
    }
    

context包的设计旨在简化在不同部分之间传递截止日期、取消信号和请求范围数据的方式,特别是在并发环境中。使用context包可以更好地管理资源、控制执行时间和处理取消操作。

基础使用

基础的context包使用示例,演示如何创建上下文、设置截止日期、取消上下文等基本操作:

package main

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

func main() {
	// 创建一个带有取消信号的上下文
	ctx, cancel := context.WithCancel(context.Background())

	// 启动一个goroutine执行任务,并传入上下文
	go performTask(ctx)

	// 模拟等待用户输入或其他触发条件
	fmt.Println("Press Enter to cancel the task.")
	fmt.Scanln()

	// 调用cancel函数取消上下文
	cancel()

	// 等待一段时间,以确保goroutine有足够的时间处理取消操作
	time.Sleep(time.Second * 2)
}

func performTask(ctx context.Context) {
	// 使用select监听上下文的取消信号
	select {
	case <-ctx.Done():
		// 当上下文被取消时执行的操作
		fmt.Println("Task canceled:", ctx.Err())
	default:
		// 模拟一个长时间运行的任务
		for i := 1; i <= 5; i++ {
			fmt.Println("Task is running...")
			time.Sleep(time.Second)
		}
		fmt.Println("Task completed successfully.")
	}
}

在这个示例中,我们首先创建一个带有取消信号的上下文,然后启动一个goroutine执行performTask函数。用户在控制台输入任意字符后,我们调用cancel函数取消上下文。performTask函数中使用select监听上下文的取消信号,一旦上下文被取消,任务将提前结束。在实际应用中,可以根据需要设置截止日期、传递数据等,以更灵活地管理上下文。

进阶使用

进阶的复杂示例,演示如何使用context包处理多个并发任务,并在某个任务失败或超时时取消所有任务:

package main

import (
	"context"
	"fmt"
	"math/rand"
	"sync"
	"time"
)

func main() {
	// 创建一个带有取消信号的上下文,设置总体超时为5秒
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()

	// 使用WaitGroup等待所有任务完成
	var wg sync.WaitGroup

	// 启动多个goroutine执行任务
	for i := 1; i <= 3; i++ {
		wg.Add(1)
		go performTask(ctx, i, &wg)
	}

	// 等待所有任务完成或上下文取消
	wg.Wait()

	fmt.Println("All tasks completed.")
}

func performTask(ctx context.Context, taskID int, wg *sync.WaitGroup) {
	defer wg.Done()

	// 模拟每个任务的执行时间
	taskDuration := time.Second * time.Duration(rand.Intn(10))
	fmt.Printf("Task %d started. Duration: %s\n", taskID, taskDuration)

	// 使用WithTimeout创建一个子上下文,设置每个任务的超时时间
	subCtx, cancel := context.WithTimeout(ctx, taskDuration)
	defer cancel()

	select {
	case <-subCtx.Done():
		// 当子上下文被取消时执行的操作
		if subCtx.Err() == context.DeadlineExceeded {
			fmt.Printf("Task %d timed out.\n", taskID)
		} else {
			fmt.Printf("Task %d canceled.\n", taskID)
		}
	case <-time.After(taskDuration):
		// 模拟任务的实际工作
		fmt.Printf("Task %d completed successfully.\n", taskID)
	}
}

在这个示例中,我们创建了一个带有总体超时的上下文,并启动了多个goroutine执行performTask函数。每个任务都有一个随机的执行时间,并在子上下文中设置了超时。使用select监听子上下文的取消信号,一旦有任务失败或超时,它将及时结束。通过使用sync.WaitGroup等待所有任务完成,我们确保在所有任务完成或总体超时后程序可以退出。

这种方式可以更好地控制并发任务,确保及时释放资源并在需要时取消任务。在实际应用中,可以根据具体需求调整超时时间和处理逻辑。文章来源地址https://www.toymoban.com/news/detail-813033.html

到了这里,关于golang中context详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Golang 如何基于现有的 context 创建新的 context?

    目录 基于现有的 context 创建新的 context 现有创建方法的问题 Go 1.21 中的 context.WithoutCancel 函数 Go 版本低于 1.21 该怎么办? 在 Golang 中,context 包提供了创建和管理上下文的功能。当需要基于现有的 context.Context 创建新的 context 时,通常是为了添加额外的控制信息或为了满足特

    2024年01月17日
    浏览(40)
  • 【Golang】VsCode下开发Go语言的环境配置(超详细图文详解)

    📓推荐网站(不断完善中):个人博客 📌个人主页:个人主页 👉相关专栏:CSDN专栏、个人专栏 🏝立志赚钱,干活想躺,瞎分享的摸鱼工程师一枚 ​ 话说在前,Go语言的编码方式是 UTF-8 ,理论上你直接使用文本进行编辑也是可以的,当然为了提升我们的开发效率我们还是需

    2024年02月07日
    浏览(85)
  • Golang:浅析Context包

    在golang官方文档context package - context - Go Packages中是这样介绍context包的: 在context包中定义了context类型来在不同的Goroutine 之间传递上下文,携带截止时间、取消信号以及携带上下文的系统参数(k-v)的类型。对服务器的传入请求应该创建上下文,对服务器的传出调用应该接受上

    2024年02月06日
    浏览(43)
  • golang Context应用举例

      golang标准库里Context实际上是一个接口(即一种编程规范、 一种约定)。   通过查看源码里的注释,我们得到如下约定: Done()函数返回一个只读管道,且管道里不存放任何元素(struct{}),所以用这个管道就是为了实现阻塞 Deadline()用来记录到期时间,以及是否到期。 Err()用来

    2024年02月08日
    浏览(36)
  • golang之context实用记录

    简言 WithCancel()函数接受一个 Context 并返回其子Context和取消函数cancel 新创建协程中传入子Context做参数,且需监控子Context的Done通道,若收到消息,则退出 需要新协程结束时,在外面调用 cancel 函数,即会往子Context的Done通道发送消息 注意:当 父Context的 Done() 关闭的时候,子

    2024年02月09日
    浏览(33)
  • 【golang】Context超时控制与原理

    在Go语言圈子中流行着一句话: Never start a goroutine without knowing how it will stop。 翻译:如果你不知道协程如何退出,就不要使用它。 在创建协程时,我们可能还会再创建一些别的子协程,那么这些协程的退出就成了问题。在Go1.7之后,Go官方引入了Context来实现协程的退出。不仅

    2024年01月22日
    浏览(37)
  • golang常用库包:log日志记录-uber的Go日志库zap使用详解

    Go 日志记录库:uber-go 的日志操作库 zap 使用 zap 是 uber 开源的一个高性能,结构化,分级记录的日志记录包。 go1.20.2 zap v1.24.0 高性能:zap 对日志输出进行了多项优化以提高它的性能 日志分级:有 Debug,Info,Warn,Error,DPanic,Panic,Fatal 等 日志记录结构化:日志内容记录是结

    2023年04月11日
    浏览(45)
  • golang 通过context设置接口请求超时时间

    下面是直接可应用的实例:

    2024年02月10日
    浏览(43)
  • 【Golang】golang中http请求的context传递到异步任务的坑

    在golang中,context.Context可以用来用来设置截止日期、同步信号,传递请求相关值的结构体。 与 goroutine 有比较密切的关系。 在web程序中,每个Request都需要开启一个goroutine做一些事情,这些goroutine又可能会开启其他的 goroutine去访问后端资源,比如数据库、RPC服务等,它们需要访

    2024年02月08日
    浏览(38)
  • go 上下文:context.Context

    Go语言中的上下文(Context)是一种用于在 Goroutines 之间传递取消信号、截止时间和其他请求范围值的标准方式。 context 包提供了 Context 类型和一些相关的函数,用于在并发程序中有效地传递上下文信息。 在Go语言中,上下文通常用于以下场景: 请求的传递:当一个请求从客户

    2024年02月05日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包