back

by lerno·5y ago·view on hn ↗
If I may venture a guess, it is because this way there is no limit in regard to jumps within or out of a function. Since Go retains `goto`, function based is easier to implement. In addition, non-local jumps, such ones constructed by setjmp, are fairly easily easy to resolve (just say that the jump will release all queued defers before the jump).

But I've also heard the opinion that some find the function based `defer` easier to reason about, so maybe that weighs in as well.

1 comments
I suspect that it’s a side-effect of Go’s origin in the Plan 9 compiler chain. This is really just speculation, but I’ll try to justify it.

First, early versions of Go strictly required a “return” as the final statement in a function, rather than just checking that each branch terminated successfully (i.e. you couldn’t return from both branches of an if/else, you also needed a redundant return statement afterwards). So I think initially the compiler didn’t perform the kind of escape analysis that would make block-scoped “defer” easy to implement.

Second, block-scoped defer is really equivalent to RAII via constructors and destructors in C++. Go was specifically designed as an anti-C++, an attempt to return to the roots of C and improve on it, so the designers would have been very wary of copying C++ features like RAII.

I think it was a mis-step, and they should have gone with block-scoped. Other languages have copied Go’s syntax, but they’ve uniformly opted for C++’s semantics, which in this instance are much easier to reason about (definitely not always the case with C++!)

> Go was specifically designed as an anti-C++

Ha! And still they managed to reimplement RAII and exceptions, only very very poorly.