Go Programming Experience

Intermediate

Other Languages Experience

Javascript, Lua

Related Idea

  • [ ] Has this idea, or one like it, been proposed before?
  • [x] Does this affect error handling?
  • [ ] Is this about generics?
  • [x] 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?

No, not to my knowledge in this fashion.

Does this affect error handling?

Yes.

I believe my idea is a less verbose, non-breaking, syntactic sugar for error handling that could be a more idiomatic way of handling errors.

Is this about generics?

No.

Proposal

I propose to add an error switch construct that is similar to the type switch construct that exists in Go, and (I'm less confident about this) to allow errors as conditions, or allow errors to be converted to bools. See the end of the proposal for code samples.

Language Spec Changes

Conditional statements, type conversion and assertions.

Informal Change

  1. You can use a switch statement to check for specific error values and types instead of using the errors.Is and errors.As functions and creating temporary variables, etc.
  2. You can use an error value as a condition to check if it is nil or not.

Is this change backward compatible?

Yes, error handling as it is currently could still be used as an explicit style if my proposal is implemented.

Orthogonality: How does this change interact or overlap with existing features?

It alleviates the high foot traffic of repetitious error handling without inventing a completely new syntax.

Would this change make Go easier or harder to learn, and why?

I believe it would it make easier to learn primarily because it's easier to read:

integer, err := strconv.Atoi("-42")
if err {
   panic(err)
}

"Convert -42 as a string to an integer, and if there was an error, panic with said error."

Cost Description

As Mr. Griesemer wrote on The Go Blog, introducing this would be a new idiomatic way that everyone would have to start writing error handling code. That may be moot due to the fact my change does not break existing error-handling Go code, but I digress. In addition, users who are new to Go may conflate "errors as conditions" as truthiness from other languages, and may introduces proposals like it in the future (I am against truthiness in conditionals for Go code). But, if the conversion of error to bool is implemented, that may alleviate that, but also be verbose.

Changes to Go ToolChain

No response

Performance Costs

No response

Prototype

  1. Error switch construct
func parseInteger(input string) (int, error) {
    integer, err := strconv.Atoi("-42")
    switch err := err.(error) {
    case nil:
        return integer, nil
    case strconv.ErrRange:
        return 0, errors.New("input integer out of range")
    case *strconv.NumError:
        return 0, fmt.Errorf(`failed to convert input "%d" to integer: %s`, err.Num, err.Err)
    default:
        panic(err)
    }
}

Equivalent:

func parseInteger(input string) (any, error) {
    integer, errConvert := strconv.Atoi("-42")
    var errNum *strconv.NumError
    if errConvert == nil {
        return integer, nil
    } else if errors.Is(errConvert, strconv.ErrRange) {
        return 0, errors.New("input integer out of range")
    } else if errors.As(errConvert, &errNum) {
        return 0, fmt.Errorf(`failed to convert input "%d" to integer: %s`, errNum.Num, errNum.Err) {
    } else {
        panic(errConvert)
    }
}

2a. Errors as conditions:

integer, err := strconv.Atoi("-42")
if err {
    panic(err)
} else if !err { // Contrived I know, but to demonstrate inversion
    println("Hooray!")
}

Equivalent:

integer, err := strconv.Atoi("-42")
if err != nil {
    panic(err)
} else if err == nil { // Contrived I know, but to demonstrate inversion
    println("Hooray!")
}

2b. Converting error to bool 2a. Errors as conditions:

integer, err := strconv.Atoi("-42")
if bool(err) {
    panic(err)
} else if !bool(err) { // Contrived I know, but to demonstrate inversion
    println("Hooray!")
}

Equivalent:

integer, err := strconv.Atoi("-42")
if err != nil {
    panic(err)
} else if err == nil { // Contrived I know, but to demonstrate inversion
    println("Hooray!")
}

Comment From: seankhliao

As the blog you link to indicates:

We will also close all open and incoming proposals that concern themselves primarily with the syntax of error handling, without further investigation.

Comment From: sorucoder

What does "without further investigation." mean in this context? Surely it does not mean without consideration?

Comment From: seankhliao

It does mean we will not consider any changes to error handling syntax for the foreseeable future.

Comment From: sorucoder

My mistake. However, "For the foreseeable future" and "without further investigation" imply (in my mind) that at least some consideration maybe made now or in the future and at least some investigation would be made. If my interpretation is correct (or later determined to be so), this proposal should be left open but remain as the "Not Planned" status. Otherwise, please make it clear that it will never be accepted on your issue tracker, and remove the relevant question (along with the generics question, as that also seems to be outdated).

EDIT: It seems the questions were removed entirely. My suggestion of making it clear still stands.

Regards.

Comment From: ianlancetaylor

One of the points of the blog post is for the Go team to stop spending time investigating error syntax proposals for the foreseeable future. Closing these proposals makes their status clear. They can be reopened if something changes someday. That said, the history of error syntax proposals is that there are far too many that are just minor tweaks. If we change anything at all in error syntax, in my opinion it's only worth doing if it's a major improvement. This proposal is not a major improvement. Sorry.

Comment From: sorucoder

Apologies as well. Thank you for the clarification.