In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >
Share
Shulou(Shulou.com)05/31 Report--
This article introduces you defer keywords, panic and recover example analysis, the content is very detailed, interested friends can refer to, hope to be helpful to you.
Defer keyword
The defer keyword can delay the execution of a function or statement to the end of the function statement block, that is, when the function is about to exit, even if the function ends with an error halfway, even if the function has already panic (), even if the function has already return, it will execute the object postponed by defer.
In fact, the essence of defer is that when the defer keyword is used in a function, a separate defer stack frame is created, the defer statement is pushed into the stack, and the relevant variables it uses are also copied to the stack frame (obviously copied by value). Because the stack is in LIFO mode, the stack is pressed first and then executed. Because it is a separate stack frame, even if the caller function has returned or reported an error, it can still enter the defer stack frame after them to execute.
For example:
Func main () {a ()} func a () {println ("in a") defer b () / push b () into the defer stack println ("leaving a") / / only here will b ()} func b () {println ("in b") println ("leaving b")}
The output is as follows:
In aleaving an in bleaving b
Even if the function has reported an error, or the function has been returned by return, the object of defer will execute at the last minute before the function exits.
Func a () TYPE {... CODE... Defer b ()... CODE... / / function executes an error return args / / function b () will be executed here}
Note, however, that because the scope of Go is lexical, the location of the definition of defer determines the value of the variable that it defers the object to see, not the value it sees when the object is called.
For example:
Package main var x = 10 func main () {a ()} func a () {println ("start a:", x) / output 10 x = 20 defer b (x) / / stack, and copy 20 to the stack x = 30 println ("leaving a:", x) / / output 30 / / call defer delayed object b (), output 20} func b (x int) {println ("start b:", x)}
Compare the following defer:
Package main var x = 10 func main () {a ()} func a () int {println ("start a:", x) / output 10 x = 20 defer func () {/ / stack, but no value is passed, so the internal reference x println ("in defer:", x) / / output 30} () x = 30 println ("leaving a:", x) / / output 30 return x}
The output value of the anonymous function delayed by defer above is 30. Shouldn't it see 20? Change it to the following first:
Package main var x = 10 func main () {a ()} func a () int {println ("start a:", x) / / output 10 x = 20 defer func (x int) {println ("in defer:", x) / output 20} (x) x = 30 println ("leaving a:", x) / / output 30 return x}
What is seen in this defer deferred object is 20, which is the same as the first defer b (x).
The reason is that defer delays if it is a function, it evaluates parameters and variables directly at its defined location. The copy of the copy passes the value, and the pointer meets the pointer. So, for cases (1) and (3), at the defined location of the defer, the copy of xreply 20 is given to the deferred function argument, so the internal operation of the function is always a copy of x. In the second case, it points directly to the variable that it sees, which is a global variable, and its value will be modified when it executes xroom30. By the time the defer deferred object is executed, the value of x it points to has already been modified.
Looking at the following example, put defer in a statement block and declare a new variable x with the same name in the statement block:
Func a () int {println ("start a:", x) / / output 10 x = 20 {x: = 40 defer func () {println ("in defer:", x) / output 40} ()} x = 30 println ("leaving a:", x) / / output 30 return x}
The above defer is defined in the statement block, and the x it can see is the x within the statement block, and its x points to the x in the statement block. On the other hand, when the statement block ends, the x of x _ blank 40 disappears, but because there is still a value of x pointing to 40 in defer's function, the value of 40 is still referenced by defer's function, and it will not be reclaimed by GC until the defer is finished. So when the defer function is executed, it still outputs 40.
If there is more than one defer within the statement block, the object of the defer executes as a LIFO (last in first out), that is, the defer defined first and then executed.
Func main () {println ("start...") Defer println ("1") defer println ("2") defer println ("3") defer println ("4") println ("end...")}
Output:
Start... End... 4 3 2 1
What is the use of defer? It is generally used to clean up the aftermath, such as cleaning up garbage, releasing resources, and executing defer objects regardless of whether an error is reported or not. On the other hand, defer can make these follow-up operation statements and start statements together, both in readability and security has been greatly improved, after all, you can write defer statements directly after writing the start statements, never forget to close, clean up and other operations.
For example, the operation of opening a file and closing it is written together:
Open () defer file.Close ()... Manipulate the file.
Here are some common scenarios for defer:
To open and close a file lock, release a lock to establish a connection, release the connection as an end, output end information to clean up garbage (such as a temporary file).
Panic () and recover ()
Panic () is used to generate an error message and terminate the current goroutine, which is generally thought of as exiting the function where panic () is located and the function that calls panic (). For example, if F () is called in G () and panic () is called in F (), F () exits and G () exits.
Note that the deferred object of the defer keyword is the last call to the function, and the deferred object of defer will be called even if panic occurs.
For example, in the following code, a () is called after outputting a start main in main (), which outputs start a, then panic, and panic () outputs panic: panic in a, and then reports an error, terminating the program.
Func main () {println ("start main") a () println ("end main")} func a () {println ("start a") panic ("panic in a") println ("end a")}
The implementation results are as follows:
Start mainstart apanic: panic in agoroutine 1 [running]: main.a () E:/learning/err.go:14 + 0x63main.main () E:/learning/err.go:8 + 0x4c exit status 2
Notice that neither end a nor end main above is output.
You can use recover () to capture panic () and resume execution. Recover () is used to catch the panic () error and return the error message. Note, however, that even if recover () captures panic (), the function that calls the panic () function (that is, the G () function above) exits, so if recover () is defined in G (), the code after calling the F () function in G () will not be executed (see the general format below).
The following are the more general formats of panic () and recover ():
The code below func main () {G () / / executes... CODE IN MAIN...} func G () {defer func () {if str: = recover (); str! = nil {fmt.Println (str)}} (). CODE IN G ().. The call to / / F () must come after the defer keyword F () / / the following code in this function will not be executed... CODE IN G ()} func F () {... CODE1... Panic ("error found") / / the following code will not be executed. CODE IN F ().}
You can use recover () to capture panic () and resume execution. But the following code is incorrect:
Func main () {println ("start main") a () println ("end main")} func a () {println ("start a") panic ("panic in a") / / error panic_str: = recover () println (panic_str) println ("end a")} directly after panic
The reason for the error is that panic () exits the functions a () and main () as soon as it appears. For recover () to actually capture panic (), you need to put recover () in defer's deferred object, and the definition of defer must precede the occurrence of panic ().
For example, the following is an example of a common format:
Package main import "fmt" func main () {println ("start main") b () println ("end main")} func a () {println ("start a") panic ("panic in a") println ("end a")} func b () {println ("start b") defer func () {if str: = recover (); str! = nil {fmt.Println (str)} () a () println ("end b")}
The following is the output:
Start main start b start apanic in an end main
Notice that end b and end an above are not output, but end main output.
Panic () is a built-in function (in the package builtin), and there is also a Panic () function in the log package that calls Print () to output information before calling panic (). Go doc log Panic can tell at a glance:
$go doc log Panic func Panic (v... interface {}) Panic is equivalent to Print () followed by a call to panic ().
This is the end of the sample analysis of defer keywords, panic and recover. I hope the above can be helpful and learn more. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.