Skip to content

proposal: spec: reduce error handling boilerplate using catch statement #71498

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

Closed
philippta opened this issue Jan 31, 2025 · 2 comments
Closed
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

@philippta
Copy link

philippta commented Jan 31, 2025

Proposal Details

Proposal

Reduce boilerplate of handling errors by introducing a new catch statement, which works similar to switch and select, given the implicit error value is non-nil.

// return bare error 
f, err := os.Open(src) catch err 


// return annotated error
f, err := os.Open(src) catch fmt.Errorf("open file: %w", err)


// switch on error type using a boolean expression
f, err := os.Open(src) catch {
    case os.IsNotExist(err): errors.New("file not found")
    case os.Permission(err): errors.New("permission denied")
    default: fmt.Errorf("open file: %w", err)
}

Multiple return values

Given a function has multiple return values, the catch statement would look like this:

// return bare error 
f, err := os.Open(src) catch nil, err 


// return annotated error
f, err := os.Open(src) catch nil, fmt.Errorf("open file: %w", err)


// switch on error type using a boolean expression
f, err := os.Open(src) catch {
    case os.IsNotExist(err): nil, errors.New("file not found")
    case os.Permission(err): nil, errors.New("permission denied")
    default: nil, fmt.Errorf("open file: %w", err)
}

The default case

The default case is effectively syntatic sugar for:

    case err != nil: ...

No default provided in catch block

Omitting the default case in the catch block, should result in a compilation error for being non-exhaustive.

Rationale

Adding a new symbol like ? or !, although inspired by other languages, feels out of place in Go code, which is why I believe adding a new keyword instead is a more reasonable approach.

Many of the proposals from this meta issue only handle the err != nil case, leaving it up to the developer to find a solution when trying to assert on the type of the error.

The new catch statement feels more Go-like by borrowing well-established syntax from switch and select using the case keyword to assert on the error type using a boolean expression.

Possible considerations for go fmt

Consider to align error handlers of case statements similar to how map key-value pairs are formatted:

f, err := os.Open(src) catch {
    case os.IsNotExist(err): errors.New("file not found")
    case os.Permission(err): errors.New("permission denied")
    default:                 fmt.Errorf("open file: %w", err)
}
@gopherbot gopherbot added this to the Proposal milestone Jan 31, 2025
@seankhliao seankhliao added LanguageChange Suggested changes to the Go language error-handling Language & library change proposals that are about error handling. LanguageChangeReview Discussed by language change review committee labels Jan 31, 2025
@seankhliao
Copy link
Member

Please fill out https://github.com/golang/proposal/blob/master/go2-language-changes.md when proposing language changes

@seankhliao
Copy link
Member

I believe this is sufficiently similar to #67955

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

3 participants