go: proposal: handle error in minimal way

It just cuts the lengthy if err !=nil {return … nil} away without introducing any new syntax/keyword/symbol/func, based on go compiler support that inserts the implicit return/log statements for unhandled error.

if err := f(); err !=nil {
    return err
}

to

err := f()

Would you consider yourself a novice, intermediate, or experienced Go programmer?

12 years of Golang experience (use before it was officially released)

What other languages do you have experience with?

C/C++ 20+ years, Objective-C 12+ years, shell script 20+ years C#, python, Java, Javascript: familiar for 10-20 years but not frequently used. Assembly/Fortran/Basic/Pascal/Cobol: known for many years, but rarely used

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

It is easier to learn and makes go programs more simplified in its verbose error handling. It adds no keywords, just “hide” the boilerplate error handling code with compiler support. It is like ARC in Objective-C without explicit release statement.

Has this idea, or one like it, been proposed before?

To the best of my knowledge, it has not been proposed.

If so, how does this proposal differ?

This proposal introduces no new keywords/symbols/syntax/functions (in contrast to check/handle, try, ?, etc. solutions proposed).

Who does this proposal help, and why?

Any golang user. It provides a nonintrusive error handling method.

What is the proposed change?

Propose to use compiler to auto generate return or log statement for any unhandled error value. “unhandled” means that its value after last write is not used.

If a func has an error return value, compiler will auto generate the return <empty value list of the other parameters + unhandled error value (optionally adding the func name with wrapped error to help debugging). Otherwise it generates log.Print(err) and return.

Please describe as precisely as possible the change to the language.

Compilers need to be changed to handle the error, it needs to know what error interface is and treats it specially. Also language extension/plugins & editor can be enhanced to toggle the display(or show in grayed) the implicitly generated code

What would change in the language spec?

Describe the behavior of unhandled error value.

Please also describe the change informally, as in a class teaching Go.

Go compiler will auto generate return code for unhandled error.

Is this change backward compatible?

Yes.

Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.

Show example code before and after the change.

Examples taken from standard golang lib encoding/json

func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
        b, err := Marshal(v)
        if err != nil {
                return nil, err
        }
        var buf bytes.Buffer
        err = Indent(&buf, b, prefix, indent)
        if err != nil {
                return nil, err
        }
        return buf.Bytes(), nil
}

can be changed(simplified) to

func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
        b, err := Marshal(v)
        var buf bytes.Buffer
        err = Indent(&buf, b, prefix, indent)
        return buf.Bytes(), nil
}

What is the cost of this proposal? (Every language change has a cost).

Compiler may need to analyze the unhandled error and it needs to generate the return statements for unhandled error.

How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?

vet (for warning of unused error value). Debugger needs to know the implicit control flow. Language extension for editor, or IDE need to change to know the hidden return statements as well.

What is the compile time cost?

The analyzer’s time will be increased but it is inside functions only. Minimal additional imports (log in standard lib) won’t increase much time.

What is the run time cost?

Zero additional cost

Can you describe a possible implementation?

Add a pass for compiler to scan each func’s syntax tree to check unhandled error values, and add the return statements, treating the func return as a write to error values.

Do you have a prototype? (This is not required.)

No

How would the language spec change?

Add statement to explain the implicit error handling.

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

Totally orthogonal.

Is the goal of this change a performance improvement?

No

If so, what quantifiable improvement should we expect? How would we measure it? Does this affect error handling?

Yes, it automates and simplifies error handling

If so, how does this differ from previous error handling proposals?

No new keyword introduced to avoid the cognitive burden.

Is this about generics?

No

If so, how does this relate to the accepted design and other generics proposals? What to avoid

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 16
  • Comments: 20 (10 by maintainers)

Most upvoted comments

I want to be clear that we aren’t going to do any of those things. Breaking compatibility with existing code is a huge cost. It would require a huge benefit. This suggestion is at best a small benefit, not nearly sufficient to break compatibility.

@senluowx It seems unnecessary to complicate things further. I know that my plan is not accepted and the reason, but I still want to explain. Some previous issues (such as #37174 ) mentioned only returning an error, and others using the default zero value in go, such as the case you mentioned. So my idea mentions extending defer, because if you just simplify return, you can’t handle some extra operations before return only when errors occur, and if there is a non-zero value that needs to be returned, you can assign a value after defer in the way of a named return value.