-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: context: add WithCancelReason #46273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
What would be the canonical way of using this? I’m trying to understand the usage: func foo(ctx context.Context) error {
ctx, cancel := context.WithCancelReason(ctx)
defer cancel(nil)
// doStuff waits for dial:
go doStuff(ctx)
if err := dial(ctx); err != nil {
cancel(fmt.Errorf("foo: %w", err))
return err
}
return nil
} The above doc-comment suggests that I’m still struggling to understand why we’d implement |
It seems like this can be done as a wrapper around WithCancel, returning a Context wrapper with a custom Err function. How often does this come up? Why is it important enough to add to the standard package? |
This proposal has been added to the active column of the proposals project |
It's important, at least in our internal code bases.
…On Wed, Nov 10, 2021 at 5:00 PM Russ Cox ***@***.***> wrote:
This proposal has been added to the active column
<https://golang.org/s/proposal-status#active> of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#46273 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAIHY66TKEADNYWWPHD3Y4DULL2RJANCNFSM45FJAMPQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
The documentation for // If Done is not yet closed, Err returns nil.
// If Done is closed, Err returns a non-nil error explaining why:
// Canceled if the context was canceled
// or DeadlineExceeded if the context's deadline passed.
// After Err returns a non-nil error, successive calls to Err return the same error.
Err() error If we add |
I can hazard a guess, which is related to #26356. Some of my coworkers have complained that they can’t figure out why something got cancelled, so this is really a request that cancellations explain themselves, in the form of a replacement to WithCancel. The reason people believe it should belong in the standard library is that they want the standard library to force people to write these explanations. That’s also why #26356 (comment) and others mention stack traces, which is another facet to the same problem. |
It still sounds like doing this in an external implementation of Context would still be the place to experiment with a change like this. |
Based on the discussion above, this proposal seems like a likely decline. |
Let me show you why this is not true and support from stdlib may help. Imagine we have func doOperation(ctx context.Context) error {
ctx, cancelReason := WithCancelReason(ctx)
// there is a background process which periodically checks
// that we still are allowed to perform an operation
go func() {
for {
if checkAccessLost() {
cancelReason(ErrAccessLost)
return
}
}
}()
return thirdPartyCall(ctx)
}
func thirdPartyCall(ctx context.Context) error {
ctx, close := context.WithTimeout(ctx, time.Minute)
defer close()
for {
if ctx.Err() != nil {
return ctx.Err()
}
}
} Imagine now that But standard My conclusion here: it is impossible to implement |
Your example seems to work for me, after I hacked together a version of WithCancelReason: https://go.dev/play/p/PXWS2Z0AU_X func doOperation(ctx context.Context) error {
ctx, cancelReason := WithCancelReason(ctx)
// there is a background process which periodically checks
// that we still are allowed to perform an operation
go func() {
cancelReason(errors.New("access lost"))
}()
return thirdPartyCall(ctx)
}
func thirdPartyCall(ctx context.Context) error {
ctx, close := context.WithTimeout(ctx, time.Second)
defer close()
for {
if ctx.Err() != nil {
return ctx.Err()
}
}
}
// Output:
// access lost |
Thank you very much, @sfllaw, your are right. I was not careful enough looking at stdlib |
Despite the fact it is doable in an external package I still want to emphasize:
|
No change in consensus, so declined. |
For people interested in this topic, please take a look at #51365 and see if it addresses your use cases. Thanks! |
Would you consider yourself a novice, intermediate, or experienced Go programmer?
I'd say experienced
What other languages do you have experience with?
C++, Javascript, Python, PHP
Would this change make Go easier or harder to learn, and why?
I don't think it'd change how easy or hard it is.
Has this idea, or one like it, been proposed before?
I think so? but for the life of me I couldn't find it.
Who does this proposal help, and why?
People who use
context.WithCancel
a lot and need to pass more error-context than justErrCanceled
.What is the proposed change?
It adds a new type and a function to the context package.
Is this change backward compatible?
Yes.
Show example code before and after the change.
Before:
After:
What is the cost of this proposal? (Every language change has a cost).
It doesn't add any overhead, the only cost is one extra function (+ type) in the
context
package.Can you describe a possible implementation?
https://go-review.googlesource.com/c/go/+/319892
How would the language spec change? No change
Orthogonality: how does this change interact or overlap with existing features?
It would lower the mental overhead of passing errors down to children
Is the goal of this change a performance improvement?
Possible slightly less memory allocation for that one extra channel we'd use to pass error details? not really much.
Does this affect error handling? In a way.
Is this about generics? No.
I'm not stuck on
WithCancelReason
, maybeWithError
would be better?The text was updated successfully, but these errors were encountered: