5 Gotchas of Defer in Go (Golang) — Part III
阿新 • • 發佈:2018-12-29
#4— Releasing the same resource
The section third above has one caveat: If you try to close another resource using the same variable, it may not behave as expected.
Example
This innocent looking code tries to close the same resource twice. Here, the second r variable will be closed twice. Because, r variable
func do() error {
f, err := os.Open("book.txt")
if err != nil {
return err
}
defer func() {
if err := f.Close(); err != nil {
// log etc
}
}()
// ..code...
f, err = os.Open("another-book.txt")
if err != nil {
return err
}
defer func() {
if err := f.Close(); err != nil {
// log etc
}
}()
return nil
}
Output
closing resource #another-book.txt
closing resource #another-book.txt
Why
As we’ve seen before, when defers run, only the last variable gets used. So, f variable will become the last one (another-book.txt). And, both defers will see it as the last one.
Solution
func do() error {
f, err := os.Open("book.txt")
if err != nil {
return err
}
defer func(f io.Closer) {
if err := f.Close(); err != nil {
// log etc
}
}(f)
// ..code...
f, err = os.Open("another-book.txt")
if err != nil {
return err
}
defer func(f io.Closer) {
if err := f.Close(); err != nil {
// log etc
}
}(f)
return nil
}
Output
closing resource #another-book.txt
closing resource #book.txt