-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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: the "watch" statement for easier error handling & more #40821
Comments
I disagree. It is easy to follow the happy path of the code. In well written Go code the happy path proceeds along the left hand side of the screen towards the bottom of the function. |
The proposal makes the "normal" control flow (not including panics) that previously was easy to detect by looking at return statements now hidden. Any assignment to a variable that is under "watch" can now exit the function. This proposal I think shares similar properties with the check/handle proposal listed in #40432 There also a bunch of open question about behaviour that would need to be clarified:
|
Thanks for your feedback! I thought about this, and you are right. Its way better to make it explicit, so I changed my idea and updated my comment. With my change, most of your concerns are adressed:
No
No
No, watch assignments must be in the same function as the watch.
Yes, I don't see why not. Same as with
Yes.
No,
No, watch ends before
|
To me now it looks even more like the abandoned handler/check proposal: https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md Could you please clarify what the main differences are that makes this proposal stand out it utility and avoiding problems vs the above proposal. This would help the discussion about the intent of the proposal and not reintroducing proposals that are (apart from minor details) the same. Minor details may be important so it is nice to understand the thought process behind them. |
In reply to @martisch In brief, the check/handler proposal as drafted introduces:
So yes, the idea of
|
Thanks for the list of other proposals @ianlancetaylor, let me quickly summarize them to get a better understanding of the #32795 with...handle...
#33002 check...handle
#32804 expect
#33266 on
#33387 try...except
So basically, I can see two groups here, one is introducing two keywords (with the indented code problem) and with the implicit error checking problem (#33002 is even doing an implicit secret check of a otherwise voided return value), and the other group where we have some sort of keeping an eye on |
After reading all of the other proposals, I noticed most of them use an example func CopyFile(src, dst string) (err error) {
var r, w *os.File
watch err {
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
}
r, err != os.Open(src)
defer r.Close()
w, err != os.Create(dst)
if _, err := io.Copy(w, r); err != nil {
w.Close()
os.Remove(dst)
err != err
// err != errors.Wrap(err, "Copy") is an alternative
}
if err := w.Close(); err != nil {
os.Remove(dst)
err != err // same as in the original example
// err != errors.Wrap(err, "Close") is an alternative
}
}
|
It does not seem like a good idea to reuse In effect it seems that this proposal is using The differences between this proposal and earlier proposals that were declined seem fairly subtle. |
Based on the discussion above, this is a likely decline. Leaving open for four weeks for final comments. |
I changed my proposal to use |
For what it's worth |
I think you guys are right and I like to retreat my proposal. I liked the idea to have a „jump to“ block like „watch“, but it needs a clearer code path when called. Maybe the idea to treat errors as values is the right way to do. After all I guess we all got used to it anyway over the last years... |
Go 1
When I started with a Go a few years ago, I was forced to wrap my head around the error management as it is today in Go. Being used to
throw
,try
,catch
and friends in other languages it really felt weird to work with errors as values.Today, I think it is a great thing that Go did not give way to the pressure to add something like
try
...catch
.Don't get me wrong, I like the way errors are handled as values, I think it is better than any of the alternatives which I heard of over the last two years.
However, working a lot with stream encoding and databases it can become an annoyance to spend three extra lines after each call into a library just to make sure all errors are dealt with. It makes it hard to read and follow the "Happy Path" of the code.
Go 2
So, after the dismissed proposal of introducing the idea of the built-in
try
(which I did not favor, as it try(made try(code try(much))) harder to read) , I am suggesting a new concept of thewatch
statement.watch
The
watch
statement takes one or more comma separated variables as argument. It executes its code block when a new value is assigned to any of the watched variables.Think of it as a sibling to
defer
,defer
executes right before anyreturn
in the same function,watch
executes right after a new value is assigned to the watched variables.So the code above would look something like this:
watch
would only be allowed at the top level of a function (likedefer
)watch
can watch one or more variables (separated by comma)=!
for the watch to runw
watch
is not limited to be used just with errorsMy own opinion
I know that this is a little weird to read at first (the code above can
return
at anywErr
assignment), but I think I would get used to this very quickly and it would save a lot of repetition and would let one focus more on the "Happy Path" in your code.If this idea is embraced, we could think about allowing
watch
in more scopes, may be even on the package level...Please comment
I would love to hear everybody's opinion on this. What could you imagine to use
watch
for, if not errors?The text was updated successfully, but these errors were encountered: