首页 >后端开发 >Golang >为什么你应该总是延迟取消 Go 中的上下文?

为什么你应该总是延迟取消 Go 中的上下文?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-11-14 10:00:03166浏览

Why Should You Always Defer Canceling a Context in Go?

取消 Context 失败:后果和解决方法

在 Go 的并发环境中,Context 控制着 goroutine 的生命周期和行为。它提供了一种传播截止日期、取消信号和其他重要信息的方法。但是,未能正确取消 Context 可能会导致不良后果。

考虑以下代码片段:

func Call(ctx context.Context, payload Payload) (Response, error) {
    req, err := http.NewRequest(...) // Some code that creates request from payload
    ctx, cancel = context.WithTimeout(ctx, time.Duration(3) * time.Second)
    defer cancel()
    return http.DefaultClient.Do(req)
}

这里创建了一个新的 Context,超时时间为 3 秒。如果没有 defer cancel() 语句,该函数将在不显式取消 Context 的情况下返回。这会触发 go vet 发出警告:

context 返回的取消函数。WithTimeout 应该被调用,而不是丢弃,以避免上下文泄漏

上下文泄漏及其影响

那么,如果Context没有被取消会发生什么呢?这种遗漏会在系统中造成“泄漏”。负责处理 Context 取消的 goroutine 无限期地保持活动状态,即使它没有任何作用。如果这种浪费的资源在程序中频繁发生,可能会导致显着的内存开销。

最佳实践:立即取消

为了避免上下文泄漏,最好的做法是立即推迟取消( )在使用 WithCancel() 或 WithTimeout() 创建新的 Context 后。这确保了函数返回后立即执行取消逻辑,无论是否有任何早期返回或异常。

总而言之,忽略取消 Context 可能会导致 goroutine 无限期运行,从而导致内存泄漏。为了防止这种情况,请始终在使用 WithCancel() 或 WithTimeout() 创建新上下文后立即推迟取消函数。

以上是为什么你应该总是延迟取消 Go 中的上下文?的详细内容。更多信息请关注PHP中文网其他相关文章!

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