Introduction
Resource Acquisition and Initialization means the following:
- When we create an object, we make sure it gets all the things it needs.
- When we no longer need the object, we clean up and give back any resources it was using.
In some programming languages like Rust, this is built into the language. But in Go, which is not entirely object-oriented, we can do something similar using the “defer” keyword.
Implementation in Go
In this example, we’ll create a simple windowing system. In this system, a window only has a title.
The Window
struct looks like this:
type Window struct {
title string
}
Now we need to able to create and destroy a window:
func create(title string) Window {
fmt.Printf("Creating window with title %s\n", title)
return Window{
title: title,
}
}
func destroy(window Window) {
fmt.Printf("Destroying window with title %s\n", window.title)
}
We also need some methods to open and close the window:
func (w *Window) open() {
fmt.Printf("Opening window with title %s\n", w.title)
}
func (w *Window) close() {
fmt.Printf("Closing window with title: %s\n", w.title)
}
Now let’s see how this works:
func main() {
window := create("My window")
defer destroy(window)
window.open()
window.close()
}
A quick summary:
- We create a window
- The
defer
statement ensures that thedestroy
function is called just before the function ends. Even thoughdefer
is written as the second statement, it is executed last. - Then we open and close the window
Conclusion
This pattern is not very hard to understand. It’s important to remember it to make sure you acquire and release resources properly. In Go, where there are no built-in object destructors, the defer
statement helps us simulate some of that functionality while keeping the code clear and easy to maintain.