Notes
A Better Go Defer
Go has a defer
statement built into the language which allows a function to be executed at the end of another function. This is pretty useful in particular for cleanup (e.g. closing a file handle) or for recovering from errors (because Go code usually contains a lot of if err != nil { return err }
and scattering cleanup code everywhere can be visually distracting).
// Real working go code
// Prints out "Start\nmain\nClose
// https://repl.it/@varsnap/Go-Defer-Example
package main
import "fmt"
type Instrumenter struct {}
func (i *Instrumenter) Start() *Instrumenter {
fmt.Println("Start")
return i
}
func (i *Instrumenter) Close() {
fmt.Println("Close")
}
func main() {
i := Instrumenter{}
defer i.Start().Close()
fmt.Println("main")
}
The funny thing is, although Go has first-class support for functions, defer
statements take a a function call as an argument, not just a function declaration or function name - i.e. defer run()
and not defer Run
. While this may be a minor annoyance while programming, it can be pretty unintuitive when combined with a factory pattern that might use defer
with a double function call.
I humbly propose (with heavy doubt it’ll be implemented) that the defer
syntax be changed so that defer
accepts a function rather than a function call as an argument, thereby making defer
accept a continuation that can be invoked at the end of a function call (this does cause some problems with variable mutations that may happen later on, which become even more complicated when exception handling is introduced, but hopefully it can be worked out). I also propose that defer
be changed from a built-in statement into a function that can accept a continuation as a parameter.