defer is not a proper replacement for destructors. One need to write it manually each time in each function where some cleanup is needed. It's easy to forget to do so or to do this in a wrong way. Destructors in the other hand are called automatically and all cleanup logic is written exactly once (within destructor body).
Usually destructors can't fail. But for rare cases like with close() you can write a helper function (static method) which destroys the given object and returns an error if has one.