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.