[Go] Defer keyword
defer
make sure the operation will be executed at the end of a function.
func loadChampions() ([]champion, error) {
file, err := os.Open("tft_champions.json")
if err != nil {
return nil, err
}
defer file.Close()
var champions []champion
for {
if err := json.NewDecoder(file).Decode(&champions); err == io.EOF {
break
} else if err != nil {
return nil, err
}
}
return champions, nil
}
Notice that even we write defer file.Close()
after os.Open
, it doesn't mean it will close the file right away, file will be close by the end of the function.
Key Points about defer
:
-
Resource Management: It's a best practice to use
defer
for closing files, network connections, or releasing other resources. This pattern helps prevent resource leaks, which can lead to performance issues or crashes due to exhausted resources. -
Order of Execution: If multiple
defer
statements are called within the same function, they are executed in the reverse order they were deferred. This LIFO (Last In, First Out) execution order is particularly useful when the order of operations for cleanup is important. -
Error Handling and Cleanup: In functions with complex error handling and multiple return points,
defer
ensures that cleanup actions are performed without needing to duplicate cleanup code before each return statement. -
Deferred Function Arguments: The arguments of a deferred function are evaluated when the
defer
statement is executed, not when the deferred function is actually called. This is an important distinction when deferring a call with arguments that may change later in the function. -
Panic Recovery:
defer
can also be used in conjunction with recovery from panics (unexpected errors), allowing a program to recover from an error state gracefully or to perform necessary cleanup before crashing.