This is a creation in Article, where the information may have evolved or changed.
52. Toad Notes Go language--defer usage scene
1. Simplify the recycling of resources
Like what:
Mu. Lock ()
Defer MU. Unlock ()
Of course, defer also has a certain amount of overhead, but also to avoid the use of defer to save performance.
From the point of view of simplifying the release of resources, defer resembles a syntactic sugar, which seems not to be necessary.
2. capture of panic anomalies
In addition to simplifying the release of resources, defer is an integral part of the Go Language anomaly framework.
In the go language, panic is used to throw exceptions, and recover is used to catch exceptions. Recover can only be used in defer statements, calling recover directly is not valid.
Like what:
Package Main
Import "FMT"
func Main () {
f ()
FMT. PRINTLN ("returnednormallyfromF.")
}
func f () {
deferfunc(){
ifr:=recover(); r!=Nil{
FMT. Println ("recoveredinF", R)
}
}()
FMT. Println ("callingG.")
g ()
FMT. PRINTLN ("returnednormallyfromG.")
}
func g () {
Panic("ERROR")
}
Therefore, if you want to capture the function exceptions in the go language, you cannot leave the defer statement.
3. Modify the return value
Defer can also be used to modify the return value of a function after a return, in addition to recover for catching panic exceptions.
For example:
Func Doublesum (A, b int) (sum int) {
Deferfunc () {
Sum *=2
}()
sum = a + b
}
4. Safe Recovery of resources
The most common use of defer is to simplify the recycling of resources. And, from a resource recovery perspective, defer is just a syntactic sugar.
For example, there is a thread-safe slice modification function that does not use the defer statement for performance:
Func Set (Mu *sync. Mutex, arr []int, I, v int) {
Mu. Lock ()
Arr[i] = V
Mu. Unlock ()
}
However, if I >= len (arr), the runtime throws an exception that is out of bounds (for example, there should not be a slice out-of-bounds exception in real-world development). In this case, Mu. Unlock () had no chance of being executed.
If you use defer, you can guarantee mu even if an exception occurs. Unlock () is called:
Func Set (Mu *sync. Mutex, arr []int, I, v int) {
Mu. Lock ()
Defermu. Unlock ()
Arr[i] = V
}
Of course, the Go Language Convention exception does not cross the package boundary. Therefore, you do not have to worry about Goroutine exception exits when calling a general function.