【问题标题】:What happens if I don't cancel a Context?如果我不取消上下文会发生什么?
【发布时间】:2024-01-16 17:07:01
【问题描述】:

我有以下代码:

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)
}

如果我没有在其中输入defer cancel() 会发生什么? go vet 发出警告

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

上下文将如何泄露,这将产生什么影响?谢谢

【问题讨论】:

    标签: go


    【解决方案1】:

    如果取消上下文失败,goroutine that WithCancel or WithTimeout created 将无限期地保留在内存中(直到程序关闭),从而导致内存泄漏。如果你经常这样做,你的记忆就会显着膨胀。最佳做法是在调用WithCancel()WithTimeout() 后立即使用defer cancel()

    【讨论】:

    • 这似乎不再是真的了?我做了一些测试,goroutine会正常释放。泄露的不是 goroutine,而是子上下文。在不取消上下文的情况下,所有子上下文都将保留在内存中,直到父上下文被取消。 play.golang.org/p/8lJ7nQOj45Y
    【解决方案2】:

    如果你使用WithCancelgoroutine 将无限期地保存在内存中。但是,如果你使用WithDeadlineWithTimeout 而不调用cancel,则goroutine 只会被保持到定时器到期。

    虽然这仍然不是最佳做法,但最好在完成资源后立即调用取消。

    【讨论】: