在 Go 中,上下文包是一个基本工具,旨在管理和共享应用程序不同层的请求范围数据、取消信号以及超时或截止日期。
context.Context 类型提供了一种以可链接、分层的方式携带截止日期、取消信号和其他请求范围值的方法。它被设计为不可变的,这意味着每个新的派生上下文都携带其父上下文的属性,同时添加新的值或行为。
将上下文想象为一个特殊的手提袋,其中包含特定任务的所有必要信息和说明。这个包可以从一个函数传递到另一个函数,确保涉及的每个人都具有相同的上下文(信息)并可以采取相应的行动。它还可以包含一个自毁按钮(取消信号),以在需要时停止操作。
在 Go 中引入 Context 之前,管理请求范围的数据和取消信号是一项繁琐的任务。开发人员必须依靠临时解决方案(例如传递自定义结构或使用全局变量)来在函数和 goroutine 之间共享数据和信号。然而,这些方法容易出错、难以维护,并且经常导致组件之间的紧密耦合。
程序中的许多操作都是异步、并发或依赖于外部系统,因此需要上下文。在这种情况下,必须有一种方法可以跨多个函数和 goroutine 传播取消信号、截止日期和请求范围的数据。
让我们考虑几个场景来说明对 Context 的需求:
想象一下您是一家熙熙攘攘的餐厅里接受订单的人。当订单到达时,您将其分配给一位熟练的厨师。但如果客户突然决定离开怎么办?你会毫不犹豫地通知厨师停止处理该订单,以免浪费食材。此场景反映了 Go 中上下文的工作方式。
假设您的应用程序向外部 API 发出 Web 请求或运行系统命令。在生产级系统中,设置超时至关重要。原因如下:
API 依赖性:想象一下您的服务依赖于外部 API。如果该 API 运行缓慢或变得无响应,您不希望系统以待处理的请求进行备份。超时可确保如果 API 调用超过指定的持续时间,关联的上下文就会取消,从而使您的应用程序能够优雅地处理这种情况。
性能下降:没有超时,外部速度慢
依赖性可能会导致级联效应。积压的请求会增加负载、降低性能并影响整体系统响应能力。通过使用带有截止日期的上下文,您可以防止此问题。
Go 中的上下文包用途广泛,可用于各种场景来管理请求范围的数据、取消信号和超时。
以下是一些常见的现实用例:
1。跨分布式服务传播跟踪 ID
在微服务架构中,跟踪不同服务之间的请求对于监控和调试至关重要。上下文包允许您跨服务边界传播跟踪 ID 和其他元数据,确保在整个请求生命周期中日志记录和跟踪信息的一致性。
2。传递身份验证令牌
在许多应用程序中,身份验证令牌或用户信息需要通过应用程序的不同层传递。 context 包提供了一种干净的方法来处理这个问题,确保身份验证信息在需要时可用,而不会用附加参数污染函数签名。
3。 WebSocket 和流 API
在 WebSocket 和流 API 中,Context 用于管理连接的生命周期并传播请求范围的数据,例如用户 ID 和会话信息。这使您可以有效地实现身份验证、速率限制和会话管理等功能。
Go 中的 context 包提供了多种创建和操作 context 对象的方法。以下是常用类型的细分:
这是最基本的上下文,可以作为一个空的起点。它不带有任何取消信号或截止日期。当不需要特定上下文时使用它。
唯一使用 TODO 代替 Background 的时候是当实现不清楚,或者上下文还不知道的时候。
通常用于主函数、初始化和测试。
ctx := context.Background()
ctx2 := context.TODO()
创建一个从父上下文派生的新上下文。WithCancel 方法返回父上下文的副本以及取消函数;调用取消函数会释放与上下文相关的资源,并且应在 Context 类型中的操作最终完成后立即调用。
用于在满足某些条件时取消 Goroutine 中的操作。
parentCtx := context.Background()
ctx, 取消 := context.WithCancel(parentCtx)
defer cancel() // 清理资源
与为自己设定截止日期类似,您可以根据上下文设定截止日期。如果达到您指定的完成时间限制,Go 将自动为您取消上下文。它创建一个从父上下文派生的新上下文,并具有特定的截止日期。
当您有完成操作的特定截止日期时很有用。
parentCtx := context.Background()
截止日期 := time.Now().Add(10 * time.Second)
ctx, 取消 := context.WithDeadline(parentCtx, 最后期限)
defer cancel() // 清理资源
使用关联的键值对创建从父上下文派生的新上下文。这允许您在上下文中存储和检索特定于请求的信息。 WithValue 接受父上下文并返回上下文副本。因此,它不会覆盖该值,而是使用新的键值对创建一个新的重复项。
用于通过上下文传递请求范围的数据,例如身份验证令牌或跟踪 ID。
parentCtx := context.Background()
userIDKey := "auth-token"
ctx := context.WithValue(parentCtx, userIDKey, "abc123")
创建具有关联超时的上下文。上下文在指定的持续时间后自动取消。 WithTimeout,允许程序在可能挂起的地方继续运行,为最终用户提供更好的体验。它接受一个简短的时间段作为参数以及父上下文,如果函数运行超出超时时间,则终止该函数。
对于设置操作截止日期很有用。
parentCtx := context.Background()
ctx, 取消 := context.WithTimeout(parentCtx, 5*time.Second)
defer cancel() // 清理资源
现在我们已经探索了 Go 中上下文的力量,让我们深入研究 GoFr 如何通过 GoFr Context 更进一步。
GoFr 是一个构建在 Go 之上的固执己见的微服务开发框架。它旨在通过提供构建健壮且可扩展的微服务的结构化方法来简化开发流程。
GoFr Context 通过创建一个包装器,完美地扩展了标准 Go 上下文包的功能。该包装器提供了一组丰富的预配置依赖项,可通过上下文对象直接访问。这个完全加载的上下文使开发人员能够从单个上下文对象无缝访问日志记录、数据库连接、底层服务、跟踪和指标 - 。
func MyHandler(c *gofr.Context) (interface{}, error) { // Logging c.Info("Processing request...") // Database access var value int err := c.SQL.QueryRowContext(c, "select 2+2").Scan(&value) if err != nil { return nil, datasource.ErrorDB{Err: err, Message: "error from sql db"} } // Accessing another service resp, err := c.GetHTTPService("anotherService").Get(c, "book", nil) if err != nil { return nil, err } // Creating a tracing span span := c.Trace("some-sample-work") defer span.End() // ... perform some work return value, nil }
在此示例中,请注意我们如何直接通过 GoFr Context 对象访问日志记录 (c.Info)、数据库交互 (c.SQL)、服务调用 (c.GetHTTPService) 和跟踪 (c.Trace) 等功能(c).
GoFr 上下文可在所有 HTTP 处理程序中使用,通过提供集中方式来管理应用程序的不同方面,从而极大地改善开发体验。这种集成确保开发人员可以专注于业务逻辑,同时利用 GoFr 的功能进行有效的上下文管理。
在程序设计方面,Golang 上下文包是一个非常有用的工具。 Go 中的上下文是管理请求范围数据、取消信号和截止日期的强大工具。无论您是构建微服务、API 还是 Web 应用程序,上下文都能确保干净的资源处理和一致的行为。
请查看 GoFr 及其 Github Repo,并给它 ⭐ 来支持它。
以上是理解和利用 Go 和 GoFr 中的上下文的详细内容。更多信息请关注PHP中文网其他相关文章!