This is a creation in Article, where the information may have evolved or changed.
Defer
There is a good design in the go language, the deferred (defer) statement, where you can add multiple defer statements to a function. When the function executes to the last, these defer statements are executed in reverse order, and finally the function returns. Especially when you are doing some open resources operation, encountered errors need to return early, before returning you need to close the corresponding resources, otherwise it is easy to cause problems such as resource leakage. As shown in the following code, we generally write open a resource that works like this:
Func ReadWrite () bool { file. Open ("file")//Do some work if Failurex { file. Close () return False } if Failurey { file. Close () return False } file. Close () return True}
We see a lot of repetitive code on it, Go'sdefer
Effectively solves this problem. With it, not only is the amount of code reduced a lot, but the program becomes more elegant. Indefer
The function specified later is called before the function exits.
Func ReadWrite () bool { file. Open ("file") defer file. Close () if Failurex { return false } if Failurey { return false } return True}
If there are many callsdefer
Sodefer
is in LIFO mode, so the following code will output4 3 2 1 0
For I: = 0; I < 5; i++ { defer FMT. Printf ("%d", I)}
The first impression that defer gave me was that, like in Java,
try {
}finally {
}
My current understanding is that in the function block using defer, is the function corresponding to a stack space, advanced and out. Call the stack at the end of the function to start the defer operation.
If an object is created that consumes memory and needs to be closed in a timely manner, defer cannot be as accurate as try Finnaly.
[Plain]View Plaincopyprint?
- Package Main
- Import "FMT"
- Import "Time"
- Type User struct {
- Username string
- }
- Func (this *user) Close () {
- Fmt. Println (this.username, "Closed!!!")
- }
- Func Main () {
- U1: = &user{"Jack"}
- Defer U1. Close ()
- U2: = &user{"Lily"}
- Defer U2. Close ()
- Time. Sleep (Ten * time. Second)
- Fmt. PRINTLN ("Done!")
- }
- [Vicky@localhost goroutine]$
Package Mainimport "FMT" Import "time" type User struct { username string}func (this *user) Close () { fmt. Println (this.username, "Closed!!!")} Func Main () { u1: = &user{"Jack"} defer U1. Close () u2: = &user{"Lily"} defer U2. Close () Time . Sleep (Ten * time. Second) FMT. PRINTLN ("Done!")} [Vicky@localhost goroutine]$
[Vicky@localhost goroutine]$ Go Run defertest1.go
Done!
Lily Closed!!!
Jack Closed!!!
[Vicky@localhost goroutine]$
In fact, the thread sleep 10 seconds, U1, and U2 can already close (), but need to rely on the end of the main () function in order to defer execution.
Then try adding an internal code area to defer:
[Plain]View Plaincopyprint?
- Package Main
- Import "FMT"
- Import "Time"
- Type User struct {
- Username string
- }
- Func (this *user) Close () {
- Fmt. Println (this.username, "Closed!!!")
- }
- Func Main () {
- {
- Even with the code fast range, the main function body will still have to end before executing defer
- U1: = &user{"Jack"}
- Defer U1. Close ()
- }
- U2: = &user{"Lily"}
- Defer U2. Close ()
- Time. Sleep (Ten * time. Second)
- Fmt. PRINTLN ("Done!")
- }
Package Mainimport "FMT" Import "time" type User struct { username string}func (this *user) Close () { fmt. Println (this.username, "Closed!!!")} Func Main () { { ///Even if the code is fast-range, it still needs the main function body to end before executing defer u1: = &user{"Jack"} defer U1. Close () } U2: = &user{"Lily"} defer U2. Close () Time . Sleep (Ten * time. Second) FMT. PRINTLN ("Done!")}
Done!
Lily Closed!!!
Jack Closed!!!
[Vicky@localhost goroutine]$
Still defer's execution in done! After. So how do you get to the exact close of try finally?
[Plain]View Plaincopyprint?
- Package Main
- Import "FMT"
- Import "Time"
- Type User struct {
- Username string
- }
- Func (this *user) Close () {
- Fmt. Println (this.username, "Closed!!!")
- }
- Func Main () {
- U1: = &user{"Jack"}
- F (U1)//In such a way that U1 does not rely on the execution of the main function
- In this way, U2 does not rely on the execution of the main function
- U2: = &user{"Lily"}
- M: = Func () {
- Defer U2. Close ()
- U2 do somthing
- // }
- M () <pre class=plain name= "code" > func () {
- Defer U2. Close ()
- U2 do somthing
- } () </PRE> time. Sleep (Ten * time. Second) fmt. PRINTLN ("Done!")} Func f (U *user) {defer u.close ()//U1 do gomething}
Package Mainimport "FMT" Import "time" type User struct {username String}func (this *user) Close () {fmt. Println (this.username, "Closed!!!")} Func Main () {u1: = &user{"Jack"} f (U1)//In such a way that U1 will not rely on the execution of the main function//Such a way, U2 will not rely on the execution of the main function U2: = &user{"Lily"}//M: = Func () {//defer U2. Close ()/////U2 do somthing//}//M () <div class= "Dp-highlighter bg_plain" ><div cl ass= "Bar" ><div class= "Tools" ><strong>[plain]</strong> <a target=_blank class= "Viewsource" title= "View plain" href= "http://blog.csdn.net/eclipser1987/article/details/12089271#" >view plain</a>< A target=_blank class= "CopyToClipboard" title= "copy" href= "http://blog.csdn.net/eclipser1987/article/details/ 12089271# ">copy</a><a target=_blank class=" Printsource "title=" print "href=" http://blog.csdn.net/ eclipser1987/article/details/12089271# ">print</a><a Target=_blank CLass= "About" title= "?" href= "http://blog.csdn.net/eclipser1987/article/details/12089271#" >?</a><a Target=_blank href= "http://blog.csdn.net/eclipser1987/article/details/12089271" ></a></div></ Div><ol><li class= "alt" ><span><span>func () { </span></span ></li><li><span> defer u2. Close () </span></li><li class= "alt" ><span> // u2 do somthing </span></li><li><span } () </span></li></ol></div><pre style= "Display:none" class= "plain" name = "Code" > func () {defer U2. Close ()//U2 do somthing} ()
Time. Sleep (Ten * time. Second) fmt. PRINTLN ("Done!")} Func f (U *user) {defer u.close ()//U1 do gomething}
[Vicky@localhost goroutine]$ Go Run defertest3.go
Jack Closed!!!
Lily Closed!!!
Done!
The use of such a method, depending on the unreasonable, but there is the need for existence. In most cases, it can be used in situations such as u1,u2 that consume very much memory, or the CPU, and then execute the time process without too many associations. It retains the functional characteristics of the defer and satisfies the conditions of precise control of the range!