golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
121.33k stars 17.38k forks source link

context: add WithoutCancel #40221

Closed CAFxX closed 1 year ago

CAFxX commented 4 years ago

What

I propose to add a WithoutCancel function in context that, given a parent Context returns a new child Context with the same values of the parent, but that is not canceled when the parent is canceled. If needed, although it seems not entirely warranted given the widespread use of similar functions (see section below), this new function could initially live in x/net/context and be migrated to context later.

In addition to the above, we should clarify a point that is only laid out implicitly in the context API docs, i.e., that values attached to the Context can also be used after the Context has been canceled.

https://go.dev/cl/459016 contains the proposed implementation.

Why

This is useful in multiple frequently recurring and important scenarios:

This is doable today by not propagating the triggering event's context and replacing it instead with a new context obtained from context.Background(). This is problematic though, as the new context does not contain any of the values attached to the context of the triggering event, and these values are important to e.g., ensure correct authentication/logging/tracing/error recovery functionality (a common scenario when using a middleware-based approach to request/event handling).

As noted below with @davecheney, a nice consequence that naturally falls out of this approach is that it effectively turns cancellation into a regular context value that can be overridden in children contexts. It doesn't solve the problem of cancellation being conflated with the intent of context being just a "bag of values" (that would almost certainly require breaking changes to solve) but it's an effective step into alleviating the situation, and it's backward compatible.

As noted further below with @martisch the benefit of this approach is that it's pretty much as minimal, composable, and in line with the current design of the context package as possible, requiring a single new public API and eschewing conflating additional mechanisms (goroutines).

An important point to be made is that all existing implementations of this (see below) rely on an internal/undocumented guarantee of cancelCtx. If this proposal is shot down at least that guarantee should be explicitly documented in the exported API.

Existing implementations

Looking around it is possible to find multiple reimplementations of this proposal, almost identical but with different names. I'm not advocating for a specific name here.

Implementations are trivial and would add a single public function to context.

adamluzsi commented 1 year ago

I like @jimmyfrasche's suggestion, WithoutCancellation. It is aligned with @rsc's suggestion and with the current naming convention for constructors in the context package. It is different enough to suggest it is not just the opposite of WithCancel and includes the other cancellations.

rsc commented 1 year ago

We could bikeshed the name more, but let's just stay with WithoutCancel. We can never agree on how many l's are in Cancellation anyhow.

rsc commented 1 year ago

Based on the discussion above, this proposal seems like a likely accept. — rsc for the proposal review group

rsc commented 1 year ago

No change in consensus, so accepted. 🎉 This issue now tracks the work of implementing the proposal. — rsc for the proposal review group

CAFxX commented 1 year ago

CL ready for review: https://go-review.googlesource.com/c/go/+/459016

gopherbot commented 1 year ago

Change https://go.dev/cl/479918 mentions this issue: context: add WithoutCancel

gopherbot commented 1 year ago

Change https://go.dev/cl/486535 mentions this issue: doc: add release notes for new context functions

davidljubadev22 commented 1 year ago

CL ready for review

https://stackoverflow.com/a/75883438/1901067

Tx @CAFxX !