As a C++ developer, highlighting the lack of destructors made me curious how resource closure is typically handled in Go. A brief review suggests that it is often handled using a "defer statement", which accumulates a stack of statements to be executed when the function returns, to execute a 'close()' method. While I can see some benefit to the explicit appearance of "defer" in the source code, I think it is outweighed by the risk someone forgets to write it (or tries to close something without defer but misses a path). The execution of a destructor is inevitable and automatic.
The main issue with destructors is that it is impossible to determine by reading the code which destructors in which order at which lines may be called. Actually, destructors can be called on every line of C++ code because of exceptions. This complicates understanding code flow and makes almost impossible to write exception-safe C++ code, which properly releases resources at any exception.
While Go supports exception-like panics, they are mostly used for really exceptional cases, when the program cannot proceed further, such as out-of-range slice accces or nil pointer dereference. Almost all these cases are triggered by programming errors, which must be fixed after the panic occurs. Traditional error handling is performed explicitly in Go instead of relying on panics - the error is checked explicitly after function call. This simplifies code reading and makes easy to spot cases with missing or incorrect error handling. These tasks are almost impossible with try/catch error handling.
> The main issue with destructors is that it is impossible to determine by reading the code which destructors in which order at which lines may be called.
huh ? the destructors are just in reverse order than the declaration order