The Go language does not have destructors. Instead, it has two more dynamic mechanisms. A defer
statement may be used to run a function on function exit or when processing a panic
. A finalizer may be used to run a function when the garbage collector finds that a block of memory has nothing pointing to it and can be released. Both approaches are dynamic, in that you have to executed the defer
statement or call the runtime.SetFinalizer
function. They are have no lexical scoping; a single defer
statement in a loop can cause its argument to be called many times on function exit.
These ideas are significantly different from destructors, which are associated with a type, and are executed when an object of that type goes out of lexical scope or is explicitly deleted. Destructors are primarily used to release resources acquired by an object of the type. This is a less important concept in a garbage collected language like Go.
The absence of destructors means that Go does not support the RAII pattern, in which an object is used to acquire a mutex or some other resource for the scope of a lexical block. Implementing this in Go requires two statements: one to acquire the mutex, and a defer
statement to release the mutex on function exit. Because deferred functions are run on function exit, the mapping is not exact; you can not use this technique to acquire a lock in a loop. In fact, acquiring a mutex in a loop and correctly releasing it when a panic occurs is rather difficult in Go; fortunately it is easy to handle correctly by moving the body of the loop to a separate function. In any case, Go discourages this type of programming. Mutexes are available in Go, but channels are the preferred mechanism for synchronization.
Are defer
statements and finalizers sufficient replacement for destructors in a garbage collected language? They are for me. When I write C++ my destructors are almost entirely concerned with releasing memory. In fact, in the gold linker I often deliberately omitted destructors, because many of the data structures live for the life the program; in such a case, destructors serve only to slow down program exit. I would be interested to hear of a pattern of programming which relies on destructors for cases other than releasing memory or RAII.
Leave a Reply
You must be logged in to post a comment.