Skip to content

proposal: Go 2: call error handling functions with ... #64399

Closed
@hauntedness

Description

@hauntedness

Proposal Details

In the current Golang language, error handling requires the use of if statements and return values to check and handle errors. While this approach is effective, it introduces a lot of repetitive code and redundant error handling logic in the codebase. To simplify the error handling process, improve code readability, and maintainability, we propose enhancing the error handling syntax sugar in Golang to make it more concise and flexible.

Background:
In the existing Golang language, error handling is typically done as follows:

func Do(param string) (string, error) {
    return "", nil
}

func DoMany(param string) error {
    result, err := Do(param)
    if err != nil {
        return err
    }
    // Handle result
    return nil
}

This approach requires the use of if statements and return values to check and handle errors, resulting in a lot of repetitive code and redundant error handling logic. To simplify the error handling process, improve code readability, and maintainability, we propose enhancing the error handling syntax sugar in Golang.

Proposal:
We propose introducing the following new syntax sugar to simplify error handling in Golang:

  1. Use named optional functions as error handlers:
func check(err error) error {
    return err
}

var nilOrReturn = check

func handle(err error, param string) error {
    return fmt.Errorf("error: %w, param: %s", err, param)
}
  1. Support using syntax sugar to handle errors in function calls:
func DoMany(param string) error {
    // 1. regular error handling
    _, err := Do(param)
    if err != nil {
        return check(err)
    }

    // 2. is syntax sugar of 1
    _, err = Do(param)
    nilOrReturn...(err) // flexible naming notation

    // 3. is syntax sugar of 2, perhaps the most use case
    result1, check...err := Do(param)
    fmt.Println(result1)

    // 4. also support multiple params handler
    _, err = Do(param)
    handle...(err, param)

    // -----------------edge cases-------------------
    // 5. allow omit extra parameter?
    _, err = Do(param)
    handle...(err, /*param: default zero? */ )

    // 6. similar to 5, but a little bit make sense
    _, handle...err = Do(param)

    // 7. syntax error? many conflictions
    _, handle...(err, param) = Do(param)

    // 8. not necessary?
    inverseOrder := func(msg string, err error) error {
        return err
    }
    _, err = Do(param)
    inverseOrder...(param, err)
    return nil
}
  1. Additional Examples:
func Do2(param string) (string, error) {
    return nil, nil
}

func handle2[T any](err error) (T, error) {
    var t T
    return t, err
}

func handleMore[T any](err error, param string) (T, error) {
    var t T
    return t, fmt.Errorf("error: %w, param: %s", err, param)
}

func DoMany2(param string) (string, error) {
    result, handle2[string]...err := Do2(param)
    return result, nil
}

func DoMore(param string) (string, error) {
    result, err := Do2(param)
    handleMore[string]...(err, param)
    return result, nil
}

Apologies in advance for any lack of thoroughness, any suggestion is appreciated.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions