Skip to content
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

proposal: Error handling: error-specific type switch #70169

Closed
3 of 4 tasks
rad12000 opened this issue Nov 2, 2024 · 4 comments
Closed
3 of 4 tasks

proposal: Error handling: error-specific type switch #70169

rad12000 opened this issue Nov 2, 2024 · 4 comments
Labels
error-handling Language & library change proposals that are about error handling. LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal
Milestone

Comments

@rad12000
Copy link

rad12000 commented Nov 2, 2024

Go Programming Experience

Intermediate

Other Languages Experience

JS, C#, Java

Related Idea

  • Has this idea, or one like it, been proposed before?
  • Does this affect error handling?
  • Is this about generics?
  • Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit

Has this idea, or one like it, been proposed before?

Yes, #67316 is very similar. One of the main differences here is that this change would aligns more closely with how a switch typically works, and ends up being less verbose.

Does this affect error handling?

Yes. It attempts to make handling specific types and instances of errors less verbose, and make error handling more of a language level feature, rather than generally package level. The hope is if we make it easier, people will do it more.

Is this about generics?

No

Proposal

As I design enterprise apis, I frequently find myself needing to handle cases where an error.Is(err, target), or error.As(&err, target), or the error is simply not nil.

Language Spec Changes

I propose creating an error specific switch in Go.

ErrorSwitchStmt = "switch" [ SimpleStmt ";" ] ErrorSwitchGuard "{" { TypeCaseClause } "}" .
ErrorSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "\error" ")" .
ErrorCaseClause = ErrorSwitchCase ":" StatementList .
ErrorSwitchCase = "case" (ErrorType | error) | "default" .

Informal Change

While not a concrete example since I've made up the functions and errors involved, the following flow is one that I find myself creating often as I attempt to handle specific error cases:

validAge, err := validateAge(age)
if errors.Is(err, ErrInvalidRange) {
	age = defaultAge
	err = nil // Don't want to go into the other error cases below
}

if err != nil {
	var formattingErr FormatError
	if errors.As(err, &formattingErr) {
		responseBody := formatErrorAsBody(formattingErr)
		// send response
		return
	}

	// send generic error response
	return
}

// execute the rest of the handler logic 

I find the above code overly cumbersome, rather verbose, and unintuitive to a reader. I propose we solve this case, and many others like it by enhancing the switch statement with an error specific statement that has a behavior similar to a type switch, but some similarity with a typical value based switch as well. To ensure backwards compatibility, rather than use switch v.(error) in our guard clause, we would use switch v.(\error). Notably, no cases in the switch statement will be evaluated UNLESS err != nil.

The above example rewritten in this new syntax would look like so:

validAge, err := validateAge(age)

switch concreteErr := err.(\error) {
   case ErrInvalidRange: // Equivalent of errors.Is(err, ErrInvalidRange)
      age = defaultAge
   case FormatError: // Equivalent of errors.As(err, &FormatError)
      responseBody := formatErrorAsBody(concreteErr)
      // send response
     return
   default:
      // send generic error response
	return
}

// execute the rest of the handler logic 

Now, not only is all of my error handling in one concise code block, I've also decreased the level of nesting, and the reader can clearly see the flow of my error handling logic. I know many will feel this is a small change for a lot of work. But I have seen repeatedly people simply omit error specific logic due to the verbosity and unwieldy nature of what we have today. I feel that making error handling more of a first class citizen in Go as a language will significantly enhance the developer experience, and result in a better experience for end users as a result.

Is this change backward compatible?

Yes

Orthogonality: How does this change interact or overlap with existing features?

No response

Would this change make Go easier or harder to learn, and why?

I actually feel it will make the language EASIER to learn, as those new to go will not have to learn about a separate errors package, but instead use a switch which they are probably already familiar with.

Cost Description

This change could maybe slightly increase the cost of compilation. Of course there is also the dev cost associated with implementing it.

Changes to Go ToolChain

No response

Performance Costs

No response

Prototype

No response

@rad12000 rad12000 added LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal labels Nov 2, 2024
@gopherbot gopherbot added this to the Proposal milestone Nov 2, 2024
@seankhliao seankhliao added the error-handling Language & library change proposals that are about error handling. label Nov 2, 2024
@seankhliao
Copy link
Member

This conflates variables and types.
It also doesn't doesn't address any of the reasons #67316 was declined in #67316 (comment)

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Nov 2, 2024
@chad-bekmezian-snap
Copy link

This conflates variables and types. It also doesn't doesn't address any of the reasons #67316 was declined in #67316 (comment)

I’m not sure how it conflates them any more than the features that a switch statement offers today.

I believe it does address some of the issues in the referenced comment, since it’s a more go-like and simple syntax. Additionally, I believe it will lead to more specific error checking/handling. And this solution could be used in tandem with a some other solution solving the if err != nil. I believe you are conflating the intent behind this proposal with solving all complaints around error handling. And that isn’t the goal.

I would rather you reopen this proposal and see if it garners interest. Closing it immediately feels a little trigger happy.

@ianlancetaylor
Copy link
Contributor

Thanks, but it doesn't help to propose variations of proposals that have already been declined. We aren't going to accept them either.

In general I don't think this class of proposals helps much with the biggest problem people have with error handling, which is the repetitive boilerplate of if err != nil { return nil, err }. It just replaces it with different boilerplate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error-handling Language & library change proposals that are about error handling. LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal
Projects
None yet
Development

No branches or pull requests

6 participants