Skip to content

proposal: Go 2: error handling with magic .handleErr() method #56126

Closed as not planned
@AAlvarez90

Description

@AAlvarez90

Author background

  • Would you consider yourself a novice, intermediate, or experienced Go programmer? Intermediate
  • What other languages do you have experience with? C & C++/Java/Javascript/Ruby/PHP/Rust/Assembly/Go

Related proposals

  • Has this idea, or one like it, been proposed before? No that I am aware of.
    • If so, how does this proposal differ?
  • Does this affect error handling? Yes
    • If so, how does this differ from previous error handling proposals? Not aware of another proposal like the one I am about to create
  • Is this about generics? No
    • If so, how does this relate to the accepted design and other generics proposals?

Proposal

  • What is the proposed change?
    I propose to add a new method which can be named handleErr, unwrap or expect or to any function operation that may return a value and an error or just an error. Currently error handling feels very repetitive in many cases. After using a function we need to add about 3 lines of code to test if err != nil. What I am proposing would allow us to accomplish the same but with less code. I am not proposing to replace the existing error handling but to enhance it.
    I have been inspired by the same functionality that is available in Rust.

  • Who does this proposal help, and why?
    It helps to handle errors with less code.

  • Please describe as precisely as possible the change to the language.
    We would enhance the existing error handling mechanism by adding special functions which are evaluated at compile time and have the compiler either add code for us (add the classic if statements we would add) or exit the enclosing function's execution while simulating the same thing that happens when we manually return the error.

    • Before
func ExpelUser(userId int) error {
    
    err := findUserAndFlag(userId)
    if err != nil {
        return err
    }

    err = executeAction2(userId)
    if err != nil {
        return err
    }

    err = closeAccountAndPayUserOff(userId)
    if err != nil {
        return err
    }
    return nil
}
  • After
func ExpelUser(userId int) error {
    
    // Ends execution of ExpelUser and returns the error that findUserAndFlag returned if it's not nil
    findUserAndFlag(userId).handleErr()

    executeAction2(userId).handleErr()

    // Returns a different type of error
    closeAccountAndPayUserOff(userId).handleErr(errors.New("Error closing account"))

    return nil
}

Another example is when the function is supposed to return a value and an error

  • Before
func FindRecordOrCreateIt(data map[string]interface{}, existingId int) Record, error {
    record := new(Record)
    
    err := database.FindRecordById(&record, id)
   
     // Something else happened other than the expected NotFound
    if !err.Is(database.ErrNotFound) {
        return record, err
    }

    if record.ID != 0 {
        return record, err
    }

    err = validateUserCreateData(data)
    if err != nil {
        return err
    }

    err = createUser(&record, data)
    if err != nil {
        return err
    }
    
     return record, nil
}
  • After
func FindRecordOrCreateIt(data map[string]interface{}, existingId int) Record, error {
    record := new(Record)
    
    // Check if the error is not sentinel error database.ErrNotFound and return it along with record
    err := database.FindRecordById(&record, id).handleErrAgainst(record, database.ErrNotFound)

    if record.ID != 0 {
        return record, err
    }

    validateUserCreateData(data).handleErr()
    createUser(&record, data).handleErr()
    
    return record, nil
}

Costs

  • Would this change make Go easier or harder to learn, and why?
    I think it would make Go more enjoyable, specially around the error handling area.
    In Go we are expected to treat "Expected Errors" as error values (sentinel errors) and "Unexpected errors/Exceptions" as Error Types but we incur in a lot of IF statement repetitions to accomplish error handling. What I am proposing is to de-load the usage of if statements to check errors and return them and have a special way of dealing with that so we use IF statements to check application logic rather than both (logic and error handling).

  • Implementation tips
    As the first pass, we can have the compiler write the if statement for us when encounters a function call followed by a call to one of the special functions. Just like we do with the * and pointers. Then, in a future implementation a more comprehensive approach could be implemented.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions