-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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: Go 2: provide symbol (e.g. #) to abort/panic on non-zero return value #22122
Comments
To any detractors of this idea, note that it's purely optional. You're free to carry on writing
But if you don't need to write that repeatedly, it's much easier to see those errors that you expect to encounter, and therefore handle gracefully. |
|
Quoting myself...
What you call "proper error handling" is only proper for (1). |
This an argument for known unknowns; the known programming mistakes are annotated with your Can you please give some examples of class (2) programming errors? |
If it's an error the caller should never see, why is the function returning an error instead of just panicking itself? |
@davecheney
@mdempsky The standard and third-party libraries cannot determine whether the issue is due to a mistake in the caller, so they always return error. |
The examples you cite are already handled by the current err != nil error handling idiom. If you want to panic on that error, just write a function to do this. If you’re argument is “go developers don’t check errors” then I don’t think this is in the domain of the language to fix, that is a code review and training arena. The goal is create programs that are reliable, not that reliably panic.
… On 4 Oct 2017, at 12:40, Liam ***@***.***> wrote:
@davecheney # annotates calls that will succeed unless there is a) a bug in the program, or b) a rare mishap for which a path to recovery is unspecified. Examples:
aFd, # := os.Open(aPath) // program failed to create file, or user axed it
_, # = aFd.Read(aBuf) // program mistakenly truncated the file
# = json.Umarshal(aBuf, &aObject) // program wrote incorrect JSON
If it's an error the caller should never see, why is the function returning an error instead of just panicking itself?
@mdempsky The standard and third-party libraries cannot determine whether the issue is due to a mistake in the caller, so they always return error.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
My argument is that this
Is far more readable than this
Also it's easier to spot errors that are expected, and therefore handled gracefully, in the former. I currently do the latter, so am not seeking incentive to check for errors. But I should not have to do this when the compiler can; the Go authors made an argument against "ceremony" once upon a time! |
This is subjective, and I disagree. |
I understand |
Well there's a learning curve for any language :-) This is one of those features where, after trying it, everyone will wonder how we tolerated the previous regime for so long -- i.e. meaningless error-checks after function calls that always work in a sane system. |
History dictates few people actually think in this manner. Everyone thinks their thing is the best, but the best thing is actually the thing with the least things. I disagree not because I don't want to write it, but because I don't want to read it. Choice breeds entropy and resistance to choice is a powerful undocumented feature of the language! |
It doesn't bother me to write One nice feature of C++ exceptions is that an uncaught exception stops execution, with no per-call ceremony. Go would benefit from that. If you enjoy ceremony, keep performing it; just don't impose it on those of us who don't. |
Again that is a subjective statement. My (admittedly equally subjective) position is the error handling boilerplate, while somewhat tedious to write, is extremely regular and when it is _not_ present that sticks out like a sore thumb in code review and alerts me to the fact that something clever is being attempted and that I need to pay close attention.
The less subjective, possibly because of its wide acceptance, position is Go is a language which optimises for the reader, at the expense of some brevity on the part of the writer. This design choice is considered to be a good thing, and unlikely to change.
… On 5 Oct 2017, at 17:48, Liam ***@***.***> wrote:
It doesn't bother me to write if err != nil { panic(err) } after most library calls, but it is bothersome to read in a long sequence of calls, as the normal logic flow is repeatedly interrupted with meaningless statements.
One nice feature of C++ exceptions is that an uncaught exception stops execution, with no per-call ceremony. Go would benefit from that. If you enjoy ceremony, keep performing it; just don't impose it on those of us who don't.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
As I have stated, this proposal's aim is precisely to optimize for reading the code:
It also benefits debugging, because it generates a stack trace from the failure point, which you don't get if you do |
As a general comment, I do not believe there is such thing as an "optional" feature for a programming language. Several decades of programming experience has shown that if a feature is in a language, it will be used. And once a feature is used, all Go programmers will have to deal with it, as there are very few programmers that work on only code they themselves have written. |
Alright, to be rigorous: It is optional for the Keeper of Code Style for the project. Notwithstanding the myth of a Single Go Style promoted by gofmt, there are numerous stylistic choices available, and implicit vs explicit abort-on-incorrect-program would be one more. PS: to those who read the original proposal shortly after I posted, I have since revised it several times for clarity. |
Which is unfortunate and should be reduced. Freedom from a feature is beneficial as much as, if not more, than the freedom to choose. |
Coding is principally a communications discipline for most coders. Humans tailor communication methodology/style based on their actual circumstances, colleagues, challenges etc. It is thoughtless to assert that an externally-defined scheme would be superior for many, let alone most, such situations. I filed this proposal because it makes my code (with heavy use of os.File) far easier to read -- and I already use one-line error checks! It does the same for many others using similar libraries. If you don't use a library which returns numerous errors that you will/should never see, you wouldn't see the value on first glance. |
There doesn't seem to be much support for this specific proposal. There is a lot of discussion of error handling over in #21161, so closing this one in favor of that. |
A distinction I have not seen raised in #21161:
There are two broad classes of error
Errors due to Unacceptable Input: A correct program handles them gracefully as they are inevitable.
Errors due to Programming Mistake: A correct program does not see them. If they arise, the program is incorrect and therefore unpredictable; it should abort.
In C, one handles (2) with
err = f(a); assert(err==0);
In C++ uncaught exceptions cause abort without explicit encouragement.
In Go today, we see
if err != nil { log.Fatal(err) }
(or panic if a stack trace is desired) after every function call that cannot fail in a correct program on a sane system. Such statements are essentially meaningless, and make the logic harder to follow. The compiler should handle this for us.Therefore let
#
(a variant of_
) specify abort-with-stack-trace for a non-zero return value (i.e. it's noterror
specific).This is not incompatible with any separate feature that adds context when handling (1), as discussed in #21161.
This results in dramatically less ceremony:
If
#
is not sufficiently noticeable,##
could be used.As an aside, I use the following instead of log.Fatal(err) or panic(err):
The text was updated successfully, but these errors were encountered: