One big flaw in Go-style `defer` is that error handling and scoping are an afterthought, and it's disappointing to see this is not improved upon in this proposal (at least as I understand the proposal).
I do think this matters in practice. If I have a `func whatever() error` IME it's a common to accidentally do something like `defer whatever()` without catching handling the error. To work around that you'd need to do something like the following.
var err error
defer func() {
err = whatever()
}
For me personally: ugh. I understand the "received wisdom" is to just structure your code differently. I don't think that's reasonable, because cleanup code is often complicated, often can fail, and is generally vastly less well-tested/exercised. YMMV, my experience is that, because of these things, the dispose-path bugs tend to be disproportionately bad. Error handling facilities that treat the dispose path as by-default not worth insuring are IMO setting users up to have a very bad time later.
While we're fixing up the error handling, I really think it's not an accident that "`defer` in a loop does not terminate in the loop, but at the end of the function" is such a frequent misunderstanding. Yes the docs are clear, but all languages spend a lot of time training you on lexical scoping, and lexically-defined disposal lifetimes (e.g., C#'s `using` or Python's `with`) are a natural extension of that training. Those implementations to varying degrees have the same error handling problem, but with some effort I really think a better world is possible, and I don't think we have to expand this to full-on RAII to provide such semantics.
Yes, for better or for worse, I think the ethos of Go is pretty much "a mulligan on C". Every C project re-implements a bespoke hash table, struggles with Unicode strings, spends a lot of time on memory management, gets tripped up on dynamic linking, and so on. If otherwise like C but are tired of those things, guess which language is perfect for you?
I do think this matters in practice. If I have a `func whatever() error` IME it's a common to accidentally do something like `defer whatever()` without catching handling the error. To work around that you'd need to do something like the following.
For me personally: ugh. I understand the "received wisdom" is to just structure your code differently. I don't think that's reasonable, because cleanup code is often complicated, often can fail, and is generally vastly less well-tested/exercised. YMMV, my experience is that, because of these things, the dispose-path bugs tend to be disproportionately bad. Error handling facilities that treat the dispose path as by-default not worth insuring are IMO setting users up to have a very bad time later.While we're fixing up the error handling, I really think it's not an accident that "`defer` in a loop does not terminate in the loop, but at the end of the function" is such a frequent misunderstanding. Yes the docs are clear, but all languages spend a lot of time training you on lexical scoping, and lexically-defined disposal lifetimes (e.g., C#'s `using` or Python's `with`) are a natural extension of that training. Those implementations to varying degrees have the same error handling problem, but with some effort I really think a better world is possible, and I don't think we have to expand this to full-on RAII to provide such semantics.