Skip to content

proposal: Proposal for Automatic Error Handling in Go #70151

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
1 of 4 tasks
fastknifes opened this issue Nov 1, 2024 · 4 comments
Closed
1 of 4 tasks

proposal: Proposal for Automatic Error Handling in Go #70151

fastknifes opened this issue Nov 1, 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

@fastknifes
Copy link

Go Programming Experience

Intermediate

Other Languages Experience

python,java,c,nodejs,swift,php,go

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, the idea of simplifying error handling in Go has been proposed before in various forms, though not necessarily with the same implementation as this proposal.

Does this affect error handling?

Yes, this proposal does affect error handling, but in a positive way. Here are some key points on how it influences error handling in Go:

  • Simplification of Error Handling: The primary goal of the proposal is to simplify the repetitive nature of error handling in Go. By introducing the errctx context, developers can avoid writing multiple if err != nil checks throughout their code, leading to cleaner and more concise code.
  • Centralized Error Management: The proposed mechanism allows developers to define a centralized error handling strategy through the context’s handler function. This means that common error handling patterns can be defined once and reused, reducing code duplication and improving maintainability.
  • Improved Readability: With the use of errctx, the intent of the code becomes clearer. Instead of having multiple error checks cluttering the logic, the error handling is encapsulated within the context, enhancing the overall readability of the code.
  • Error Propagation: The proposal maintains the existing pattern of error propagation by returning errors from functions. It does not eliminate error returns; rather, it provides a more elegant way to manage them. The context allows developers to handle errors in a more controlled manner while still adhering to the standard practice of returning errors.
  • Cognitive Load Reduction: By reducing the number of explicit error checks, the proposal helps lower the cognitive load on developers. They can focus more on the business logic of their code rather than on boilerplate error handling.
  • Backward Compatibility: The proposal does not disrupt existing error handling paradigms. Developers can choose to adopt the new mechanism at their own pace, and existing codebases can continue to function without modification.

In summary, the proposal positively affects error handling by making it simpler, more organized, and easier to read, while remaining compatible with Go's existing error handling practices. It encourages cleaner code and enhances the overall developer experience without introducing breaking changes.

Is this about generics?

No, this proposal is not about generics. The focus of the proposal is on simplifying error handling in Go by introducing a context-based error handling mechanism (errctx) that reduces the repetitive if err != nil checks.

Proposal

First of all, I would like to note that I was very reluctant to make this step, but I really think it is simple and will greatly simplify error handling in Go.
Goal: Simplify repetitive if err != nil blocks across the codebase.

Example: Error handling.

if err != nil {
    // do stuff
    return value1, value2, err
}

We can generalize the inner block of the if statement, but we still have to process the result with an if statement to exit the outer function. This leads to too many lines of code for something that could be a one-liner.

How it will work

package errctx

type ErrorContext struct {
    err error
    handler func(error) bool // returns false to stop execution
}

// Create a new ErrorContext
func New(handler func(error) bool) *ErrorContext {
    return &ErrorContext{handler: handler}
}

// Execute a function in the context and capture errors
func (ec *ErrorContext) Do(fn func() error) {
    if ec.err != nil {
        return // If there's already an error, stop further execution
    }
    ec.err = fn()
    if ec.err != nil && ec.handler != nil {
        if !ec.handler(ec.err) {
            return // If handler returns false, stop further execution
        }
    }
}

// Get the final error
func (ec *ErrorContext) Err() error {
    return ec.err
}

Usage Example

package main

import (
    "errors"
    "fmt"
    "errctx"
)

func step1() error {
    // Simulate an operation
    return nil
}

func step2() error {
    return errors.New("step2 failed")
}

func step3() error {
    return nil
}

func main() {
    ctx := errctx.New(func(err error) bool {
        fmt.Println("Error encountered:", err)
        return false // Stop further execution
    })

    ctx.Do(step1)
    ctx.Do(step2) // Triggers error handling
    ctx.Do(step3) // Will not execute because ctx has an error

    if ctx.Err() != nil {
        fmt.Println("Final error:", ctx.Err())
    }
}

Requirements

  • The function after the ctx.Do() call should return one or more arguments.
  • The first return value should be a boolean indicating success.
  • Any additional return values should match the corresponding outer function types.
    This approach will greatly reduce the number of lines written for error handling in an application. Developers can implement general error handlers and utilize them succinctly, leading to more maintainable code.
    This method is not only helpful in error handling but also aids in reducing the cognitive workload in functions with multiple if, else, or switch statements.

Language Spec Changes

No response

Informal Change

No response

Is this change backward compatible?

Yes, the proposed change for automatic error handling in Go is designed to be backward compatible. Here are a few key points explaining why:

  • No Breaking Changes: The proposal introduces a new package (errctx) and a new mechanism for error handling, but it does not modify or remove any existing language features or error handling paradigms in Go. Existing code that relies on traditional error handling (i.e., if err != nil) will continue to function without any changes.
  • Optional Usage: Developers can choose whether or not to adopt the new errctx approach. Those who prefer the traditional error handling method can continue using it alongside the new method. This means that the proposal does not impose any changes on existing codebases, allowing developers to transition at their own pace.
  • Seamless Integration: The errctx context can be utilized in new functions or existing functions without altering their fundamental behavior. Existing functions can be wrapped in the new error handling context as needed, ensuring compatibility with existing error patterns.
  • Compatibility with Existing Patterns: The proposal complements Go’s existing error handling patterns rather than replacing them. Developers can mix and match the new context-based error handling with traditional methods as they see fit, which maintains the language's flexibility.

Overall, since the change does not disrupt current functionality or the syntax of the language, it remains backward compatible, allowing developers to integrate it without affecting existing code.

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?

No response

Cost Description

No response

Changes to Go ToolChain

No response

Performance Costs

No response

Prototype

No response

@fastknifes fastknifes added LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal labels Nov 1, 2024
@gopherbot gopherbot added this to the Proposal milestone Nov 1, 2024
@randall77
Copy link
Contributor

Whether the handler returns true or false, (*ErrorContext).Do returns immediately. Did you mean something else? A setting of ec.err to nil, or not nil, somehow?

@DeedleFake
Copy link

DeedleFake commented Nov 1, 2024

I'm not quite sure that I follow the descriptions around the examples as the examples themselves don't seem to show the functionality that the text describes. How would you write the following using your proposal?

v, err := strconv.ParseInt(str, 10, 0)
if err != nil {
  return fmt.Errorf("failed to parse string: %w", err)
}

@fastknifes
Copy link
Author

I'm not quite sure that I follow the descriptions around the examples as the examples themselves don't seem to show the functionality that the text describes. How would you write the following using your proposal?

v, err := strconv.ParseInt(str, 10, 0)
if err != nil {
  return fmt.Errorf("failed to parse string: %w", err)
}

This proposal is primarily aimed at addressing the repeated use of if != nil statements. If your code does not contain any duplicate if != nil statements, you may choose not to use this proposal. However, if if != nil appears multiple times, it is recommended to implement this proposal.

    ctx.Do(func() error {
        var err error
        result, err = strconv.ParseInt(str, 10, 0)
        return err
    })

    if ctx.Err() != nil {
        return 0, fmt.Errorf("failed to parse string: %w", ctx.Err())
    }

@ianlancetaylor ianlancetaylor added the error-handling Language & library change proposals that are about error handling. label Nov 1, 2024
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