Skip to content

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

Duplicate of#67955
@philippta

Description

@philippta

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)
}

Activity

added this to the Proposal milestone on Jan 31, 2025
added
LanguageChangeSuggested changes to the Go language
error-handlingLanguage & library change proposals that are about error handling.
LanguageChangeReviewDiscussed by language change review committee
on Jan 31, 2025
seankhliao

seankhliao commented on Jan 31, 2025

@seankhliao
Member
seankhliao

seankhliao commented on Jan 31, 2025

@seankhliao
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

Metadata

Metadata

Assignees

No one assigned

    Labels

    LanguageChangeSuggested changes to the Go languageLanguageChangeReviewDiscussed by language change review committeeProposalerror-handlingLanguage & library change proposals that are about error handling.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @gopherbot@seankhliao@philippta

        Issue actions

          proposal: spec: reduce error handling boilerplate using catch statement · Issue #71498 · golang/go