Skip to content

proposal: context: add WithCancelReason #46273

Closed
@OneOfOne

Description

@OneOfOne
  • 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 just ErrCanceled.

  • What is the proposed change?
    It adds a new type and a function to the context package.

// A CancelReasonFunc tells an operation to abandon its work with the specified error
// and it cannot be nil.
// A CancelReasonFunc does not wait for the work to stop.
// A CancelReasonFunc may be called by multiple goroutines simultaneously.
// After the first call, subsequent calls to a CancelFunc do nothing.
// The first error set is the one returned from Err().
type CancelReasonFunc func(reason error)

// WithCancelReason returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func WithCancelReason(parent Context) (ctx Context, cancel CancelReasonFunc) {}
  • Is this change backward compatible?
    Yes.

  • Show example code before and after the change.

Before:

func doStuff(ctx context.Context, errCh chan error) {
	select {
	case <-ctx.Done():
	case err := <-err:
		switch err {
		case ErrServerExploded:
			// find another server and retry again.
		}
	}
}

After:

func doStuff(ctx context.Context) {
	<-ctx.Done()
	switch err := ctx.Err() {
		case ErrCanceled:
		// nothing todo
		case ErrServerExploded:
		// find another server and retry again.
	}
}
  • 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, maybe WithError would be better?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions