The defer keyword in Go is used to ensure that a function call is executed when the surrounding function returns. Specifically, the function following defer is executed when the surrounding function exits, regardless of whether it returns normally or exits early due to an error.
Main Uses
-
Resource Cleanup: For example, closing file handles, database connections, and releasing locks.
-
Error Handling: When handling errors,
defercan be used to ensure that necessary cleanup logic is executed.
Examples
File Operation Example
gofunc ReadFile(filename string) (string, error) { f, err := os.Open(filename) if err != nil { return "", err } defer f.Close() // Ensures the file is closed when the function exits contents, err := ioutil.ReadAll(f) if err != nil { return "", err } return string(contents), nil }
In this example, defer f.Close() ensures that the file is properly closed regardless of how the function exits (normal reading or an error occurs), thus avoiding resource leaks.
Lock Operation Example
gofunc processData(data *Data) { mu.Lock() defer mu.Unlock() // Ensures the lock is released regardless of how processData exits // Process data }
In this example, defer mu.Unlock() ensures that the lock is released regardless of whether an error occurs or the function returns early during data processing, which is critical for avoiding deadlocks.
In this way, Go's defer keyword effectively simplifies error handling and resource management code, making it clearer and safer.