But its effect is huge, e.g. the prototypical usage of the keyword would be to unlock mutexes, but it is simply a huge footgun, see: https://news.ycombinator.com/item?id=30253426
If it was scope-based, there would be just as many people complaining that it isn't function based.
They _should_ be identical, unless shouldDoSideEffect changes.
Yes, mutability is bad. One shouldn't change that. But avoiding "you're holding it wrong" footguns was the original goal, right?
Don't get me wrong, having both would be nice. Maybe something like `after` for function scope and `defer` for block scope. But that starts to erode the "simplicity" of Go, I guess.
if condition_A {
acquire_A()
defer release_A()
} else if condition_B() {
acquire_B()
defer release_B()
} else {
acquire_C()
defer release_C()
}
But with block-scoped defer you'd have to write something like: if condition_A {
acquire_A()
} else if condition_B {
acquire_B()
} else {
acquire_C()
}
defer func() {
if condition_A {
release_A()
} else if condition_B {
release_B()
} else {
release_C()
}
}()
Maybe the syntax here could be better with some kind of defer-if added to the language, but it's the non-locality of the cleanup that's the real downside. The whole point of the defer keyword is to let you put cleanup right next to resource acquisition, to make code easier to audit and maintain, and we lose that here. (Also this version might not even be correct, if the conditions change their values over time.)To be honest, I think Rust's combination of destructors and move semantics is really the ideal way of doing cleanup, with C++ coming pretty close too. But given a defer keyword, I can see situations where having it block-scoped would be painful.