0

0

深入了解Go Context的用法

PHPz

PHPz

发布时间:2023-04-05 09:10:37

|

1379人浏览过

|

来源于php中文网

原创

go语言中的context,非常好用,几乎所有的go程序都使用它来传递请求范围的值。 它是一个轻量级的对象,允许跨api边界传递请求范围的值,包括取消信号、截止日期和请求id等。

在本文中,我们将深入了解Go Context的用法,了解它的优势及如何使用它来提高应用程序的性能和健壮性。

什么是Go Context?

Go Context是Go语言中的一个标准库,用于管理请求范围的值。它为应用程序提供一个轻量级的,且具有传递性的方法,用于在 goroutine 之间传递请求的变量。它主要用于传递取消请求、超时限制、跟踪日志、请求上下文以及请求数据等。

与其他编程语言中的 Context 不同,Go Context 具有一些非常特殊的性质:

  • 它是线程安全的。
  • 它的值可以跨 goroutine 传递。
  • 它可以取消或超时,以防止长时间运行或无法停止的操作。
  • 它还可以用于分离请求取消和实际操作取消。

使用场景

Go Context是非常通用的工具,可以用于不同场景下的应用程序,其中一些场景包括:

  1. Web应用程序

Web应用程序是最常见的使用场景之一。它可以轻松地管理处理 HTTP 请求所需的上下文和请求特定的元数据。在HTTP请求处理期间,Context 被用于跨 handler 传递请求ID,请求超时限制,取消信号等。例如,Context 在处理 Websocket 连接时用于跟踪会话状态。

  1. 后台服务应用程序

后台服务应用程序可能需要遍历多个 API 以为外部系统提供数据,Context 在这种应用程序中被用于完成 goroutine 更高效的终止,是这种应用程序的最佳选择。 您可以使用 Context WithCancel 标准函数来实现这一点。 如果所有的 goroutine 都使用这个 Context,那么只需要回调一次即可停止所有订阅并清理资源。

  1. 数据库和文件操作

Go Context 是处理大型文件和 DB 操作的理想工具,因为这些操作可能会耗费大量的资源和 I/O。 在这种情况下,Context 用于取消操作,以避免出现失误和运行时错误。

  1. 分布式应用程序

在微服务架构中,Context 被广泛用于从 API 传递请求范围的信息到各个服务的调用链。 在这种情况下,追踪跟踪ID存储在 Context 中,并在连接多个服务时传递。 这使得整个请求线路的追踪变得容易。

Context的用法

现在我们已经了解了 Go Context 的基础知识,接下来我们将探讨如何使用它来管理请求范围的值。

  1. 创建一个Context

在 Go 语言中,您可以使用 context.Background() 来创建一个空的顶层 context。这个 context 是全局独立的,不包含任何值。

ctx := context.Background()

您还可以使用 WithValue() 函数来创建一个带有值的 context。 例如,您可以创建一个 HTTP 请求处理的 context 带有请求数据和超时限制。

ctx := context.WithValue(
        context.Background(),
        "requestId",
        uuid.New())

ctx.Value() 函数使用这个 context 来获取 context 的值。 在下面的例子中,我们可以通过请求唯一标识符获取 Context 信息。

requestId, ok := ctx.Value("requestId").(value string)
  1. 超时信号

使用 context.WithDeadline 或 context.WithTimeout 函数,您还可以将超时信号应用于 context,以避免长时间运行的过程。

宠物商店
宠物商店

目前,PetShop已经从最初的2.0、3.0等版本,发展到了最新的4.0版本。PetShop 4.0使用ASP.NET 2.0技术开发,其中加入了众多新增特性,因此,在性能、代码数量、可扩展性等方面有了重大改善。可以说,学习PetShop 4.0是深入掌握ASP.NET 2.0技术的捷径。本节将引领读者逐步了解PetShop 4.0的方方面面,包括应用程序安装、功能和用户界面简介、解决方案和体系

下载
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

cancel() 函数被用于标记 Context 的取消状态。 在超时事件发生时,Context 将自动取消。

select {
case <-timeOutCtx.Done():
         if err := timeOutCtx.Err(); err != nil {
                   fmt.Println("Time out due to: ", err)
         }
case <-time.After(5 * time.Second):
       fmt.Println("Hooray! Request done within 5 sec")
}

在这个例子中,我们创建一个10秒的超时 Context。 select 语句等待两个 channel 上的操作。 Done() 方法,当 Context 取消或超时时,将发出一个信号。

我们通过定时器 channel 发送短消息,等待 5 秒。 因为我们 context.WithTimeout() 函数的第二个参数是 10 秒,所以应该只有选择语句中的第一条路线被执行。

  1. Context可取消

Context 在长时间的运行过程中使用,可以使用取消信号的一个特性,以避免对系统产生意外的负载。

在下面的代码段中,我们将使用 context.WithCancel() 创建一个 Context,然后使用 cancel() 函数来标记 Context 的取消状态。 给定的 goroutine 如果在 Context 取消之前完成,则通过 Done() 方法发送它的 完成信号 。

ctx, cancel := context.WithCancel(context.Background())

go func(ctx context.Context) {
      select {
             case <-ctx.Done():
                 fmt.Println("Exiting goroutine")
                 return
             default:
                  fmt.Println("Processing...")
       }
}(ctx)

// Exit after 5 sec
time.AfterFunc(5*time.Second, cancel)

在这里,我们在 goroutine 中使用 Done() 和默认分支。 如果 Context 取消或超时,Done() 方法将返回一个信号,并调用 cancel() 函数来取消 goroutine 的运行。

在主函数中,我们使用 time.AfterFunc() 函数调用这个 Context 的取消() 函数来标记 Context 的取消状态。 这将在 5 秒钟后触发 goroutine 取消操作。

  1. Context超时和取消

在处理请求的时间,我们通常需要确保 goroutine 不会无限期地等待,而需要在可接受的时间范围内执行操作。

在下面的代码段中,我们将使用 context.WithTimeout() 函数创建一个带有 5 秒超时限制的 Context。

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

select {
    case <-time.After(5 * time.Second):
       fmt.Println("Request completed")
    case <-ctx.Done():
         fmt.Println("Exit due to: ", ctx.Err())
}

我们也使用了 cancel() 函数,确保 Context 被取消时自动触发。

为了模拟一个长时间的操作,我们使用 time.After(channel)。 当 goroutine 执行时间超过 2 秒时,Context 始终会被取消。 select 语句通过检查两个 channel 的操作结果而“安全地”退出。

总结

在 Go 语言中,Context 是通用工具,用于管理请求范围的数据。它提供了一种非常强大,灵活的方法,以跨 API 边界传递请求范围的值,如取消信号、截止日期、请求 ID 等。

在本文中,我们深入探讨了 Go Context 的一些实际用例,并讨论了一些最佳实践,以优化应用程序的可维护性和性能。

随着应用程序和网络的规模增长,Context 的正确使用和管理变得非常重要。如果用得当,它可以提高应用程序的健壮性和性能,从而确保进行细粒度的请求管理。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

328

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

235

2023.10.07

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

183

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

287

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

258

2025.06.11

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

124

2025.08.07

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

503

2023.08.10

Go中Type关键字的用法
Go中Type关键字的用法

Go中Type关键字的用法有定义新的类型别名或者创建新的结构体类型。本专题为大家提供Go相关的文章、下载、课程内容,供大家免费下载体验。

234

2023.09.06

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号