-
Notifications
You must be signed in to change notification settings - Fork 17.6k
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
proposal: handle error in minimal way #57552
Comments
Please fill out https://github.com/golang/proposal/blob/master/go2-language-changes.md when proposing language changes |
What's the expected behavior of the snippet below? (adapted from your proposal) 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(), err
} |
The compiler will not complain the above code as an error due to unused error variables and will generate code with same semantics as the original code. |
What does this generate? func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
b, err := Marshal(v)
foo(err)
return b, nil
} |
This change is not backward compatible. Code like this is valid today, but would change behavior under this proposal. b, err := Marshal(v)
err = F()
return err |
A possible solution to this would be to tell the compiler where it should generate the returns. func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
b, _ := Marshal(v)?
var buf bytes.Buffer
Indent(&buf, b, prefix, indent)?
return buf.Bytes(), nil
} Correct me if I'm wrong but this would not break existing code I don't think? |
see #51146 |
Thanks for pointing me in the right direction @seankhliao. Nothing new under the sun ☀️ 😹 |
This won't change anything as err value is used by foo. |
Yes, thanks, the behavior is changed for this code. It was overlooked.
|
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. |
I have a similar idea. func foo()error{
res, err? := bar() defer handleMore(err)
} It is equivalent to: func foo()error{
res, err := bar()
if err!=nil{
defer handleMore(err)
return err
}
} It is simple, explicit, and extends |
see #36390 |
A significant change in semantics based on whether or not a variable is used is too confusing for a language like Go. The later suggestion of a Based on this, and the discussion above, and the emoji voting, this is a likely decline. Leaving open for four weeks for final comments. |
multiple returns func foo() (any, error){
res, (nil, err)? := bar()
} or
|
@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. |
I had an idea to extend original suggestion by re-using the existing keyword "return" as modifier to the error var to be managed. i.e.,
becomes
It keeps the backward compatibility as "return var" as a left-value won't be conflict with existing code, and the original keyword return exists in different context from current one which is in a left-value. Without "return" modifier, the err value would be handled in old familiar way. Also "return" can be used for any number of error variables. So that compiler will handle it one by one according to text order. e.g.,
For me it has less mental burden to use "return" modifier than any other cryptic symbols (like ?, or !) or new keywords/func(check, try) and it still looks like normal go code. The "return" keyword looks like compressing if err statement{return _, err} into a single keyword "return", which is a natural reminder of a control flow exists here: if the error value is not nil, it will be handled automatically by compiler. But I am not sure if the idea falls into existing bad cases or others may feel strange. Welcome comments. Thanks. PS: Another issue suggesting "pass err", and even "return? err" or "return if err" #37141 |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as resolved.
This comment was marked as resolved.
No change in consensus. |
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.
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
can be changed(simplified) to
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
The text was updated successfully, but these errors were encountered: