Go Series Tutorial--32. Panic and recover

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. [Panic and recover] (https://raw.githubusercontent.com/studygolang/gctt-images/master/golang-series/panic-recover-golang-2-2.png) Welcome to the 32nd chapter of [Golang Series Tutorial] (HTTPS://STUDYGOLANG.COM/SUBJECT/2). # # What is panic? In the Go language, it is common for programs to use [ERROR] (https://studygolang.com/articles/12724) to handle exception situations. The error is sufficient for most of the anomalies that occur in the program. In some cases, however, the program cannot continue to run when an exception occurs. In this case, we will use ' panic ' to terminate the program. When [function] (https://studygolang.com/articles/11892) occurs panic, it terminates the run, after executing all the [delay] (https://studygolang.com/articles/ 12719) After the function, the program control returns to the caller of the function. This process persists until all functions of the current [https://studygolang.com/articles/12342] return exit, and then the program prints out the panic information, then prints out the stack trace, The final program terminates. After we have written a sample program, we will be able to understand the concept very well. In this tutorial, we'll go on to discuss the use of ' recover ' to regain control of the program when it happens to be panic. It can be thought that ' panic ' and ' recover ' are similar to the ' try-catch-finally ' statements in other languages, except that we rarely use ' panic ' and ' recover '. And when we use ' panic ' and ' recover ', it's more elegant than ' try-catch-finally ' and the code is cleaner. # # When should I use panic? * * Note that you should use [ERROR] (https://studygolang.com/articles/12724) as much as possible instead of using panic and recover. You should use panic and recover only if the program cannot continue to run.Mechanism * *. The panic has two reasonable use cases. 1. * * An unrecoverable error has occurred and the program cannot continue running * *. One example is that the Web server cannot bind the required ports. In this case, you should use panic, because if you can't bind a port, you can't do anything. 2. * * A programming error has occurred * *. If we have a method that receives pointer parameters, others use ' nil ' as arguments to invoke it. In this case, we can use panic because this is a programming error: the ' nil ' parameter is used to invoke a method that can only receive a valid pointer. # # # Panic Example the signature of the built-in function ' panic ' is as follows: ' Gofunc Panic (interface{}) ' When the program terminates, it prints the arguments passed in ' panic '. Let's write an example and you'll know what it's used for. Let's start right now. We will write an example to show how ' panic ' works. "' Gopackage mainimport (" FMT ") func fullName (FirstName *string, LastName *string) {if FirstName = nil {panic (" runtime Error:first name cannot be nil ")} if LastName = = Nil {Panic (" Runtime Error:last name cannot be nil ")} FMT. Printf ("%s%s\n", *firstname, *lastname) fmt. PRINTLN ("returned normally from FullName")}func Main () {firstName: = "Elon" FullName (&firstname, nil) fmt. PRINTLN ("returned normally from main")} "[Run on Playground] (Https://play.golang.org/p/xQJYRSCu8S) The program above is very simple, A person's full name is printed. The ' fullName ' function on line 7th prints out the full name of a person. The function checks the ' firstName ' and ' lastName ' pointers for ' nil ' on lines 8th and 11th, respectively. If it is ' nil ', the ' fullName ' function invokes a differentThe ' panic ' of the error message. When the program terminates, the error message is printed. Running the program will have the following output: "' Panic:runtime error:last name cannot be Nilgoroutine 1 [running]: Main.fullname (0x1040c128, 0x0)/tmp/sa Ndbox135038844/main.go:12 +0x120main.main ()/tmp/sandbox135038844/main.go:20 +0x80 "Let's analyze this output and understand how panic works, And think about how the stack trace will be printed when the program panic. In line 19th, we assign ' Elon ' to ' firstName '. In line 20th, we call the ' fullName ' function, where ' lastName ' equals ' nil '. Therefore, the condition of the 11th line is satisfied, and the program occurs panic. When panic occurs, the program terminates the run, prints the parameters of the incoming panic, and prints the stack trace. Therefore, the code for lines 14th and 15th does not execute after panic occurs. The program first prints out the information passed in the ' Panic ' function: ' panic:runtime error:last name cannot be empty ' and then prints out the stack trace. The program is panic on line 12th of the ' fullName ' function, so the output shown below is printed first. "' Main.fullname (0x1040c128, 0x0)/tmp/sandbox135038844/main.go:12 +0x120" will then print out the next item on the stack. In this case, the next item in the stack trace is line 20th (because the ' fullName ' call that occurred panic is in this line), so the next print is: "' Main.main ()/tmp/sandbox135038844/main.go:20 +0x80 "Now that we've reached the top-level function that leads to panic, there's no more hierarchy, so it ends up printing. # # # When the panic occurs defer we re-summarize what panic has done. * * When a function occurs panic, it terminates the run, and after all the deferred functions are executed, the program control returns to the caller of the function. This process continues until all the functions of the current process areReturn exit, then the program prints out the panic information, then prints out the stack trace, and finally the program terminates * *. In the example above, we have no delay in invoking any functions. If there is a delay function, it is called first, and then program control is returned to the function caller. Let's modify the example above, using a deferred statement. "' Gopackage mainimport (" FMT ") func fullName (FirstName *string, LastName *string) {defer FMT. Println ("Deferred call in FullName") if FirstName = = Nil {Panic ("Runtime Error:first name cannot be nil")} if LastName = = Nil {Panic ("Runtime Error:last name cannot be nil")} FMT. Printf ("%s%s\n", *firstname, *lastname) fmt. PRINTLN ("returned normally from FullName")}func Main () {defer FMT. Println ("Deferred call in Main") FirstName: = "Elon" FullName (&firstname, nil) fmt. PRINTLN ("returned normally from main")} ' [Run on Playground] (Https://play.golang.org/p/oUFnu-uTmC) in the above code, we only modified two places, Calls to delay functions are added in lines 8th and 20th, respectively. The function will print: "This program prints,deferred the call in FullName deferred call in main panic:runtime error:last name cannot be NI Lgoroutine 1 [Running]: Main.fullname (0x1042bf90, 0x0)/tmp/sandbox060731990/main.go:13 +0x280main.main ()/tmp/ sandbox060731990/main.go:22 +0xc0 ' ' whenWhen the program is panic on line 13th, the delay function is executed first, then control returns to the function caller, and the caller's deferred function continues until it reaches the top-level calling function. In our example, the ' defer ' statement in the ' fullName ' function is executed first (line 8th). The program prints out: ' Deferred call in FullName ' and then the program returns to the ' main ' function, executing the ' main ' function for deferred invocation, and therefore outputting: ' ' deferred called in Main ' is now programmed to reach the top-level function , the function prints out the panic information, then the stack trace, and finally terminates the program. # # recover ' recover ' is a built-in function that is used to regain control of the panic process. The label for the ' Recover ' function is as follows: ' ' Gofunc recover () interface{} ' is only useful for invoking ' recover ' within the deferred function. Call ' recover ' in the delay function, you can get the error message of ' Panic ', and stop the Panic Continuation event (panicking Sequence), the program runs back to normal. If you call ' recover ' outside of the deferred function, you cannot stop the panic continuation event. Let's revise the program and use ' recover ' to get back to normal operation after the panic has occurred. "' Gopackage mainimport (" FMT ") func Recovername () {if r: = Recover (); r!= Nil {fmt. Println ("Recovered from", R)}}func FullName (FirstName *string, LastName *string) {defer recovername () if firstName = = N Il {panic ("Runtime Error:first name cannot be nil")} if LastName = = Nil {Panic ("Runtime Error:last name cannot be nil ")} FMT. Printf ("%s%s\n", *firstname, *lastname) fmt. PRINTLN ("returned normally from FullName")}func mAin () {defer FMT. Println ("Deferred call in Main") FirstName: = "Elon" FullName (&firstname, nil) fmt. PRINTLN ("returned normally from main")} "[Run on Playground] (HTTPS://PLAY.GOLANG.ORG/P/I9PP8N55C1) on line 7th, ' Recovername () ' function called ' Recover () ', returning the argument of the call ' panic '. Here we just print out the return value of ' Recover ' (line 8th). Within the ' fullName ' function, we delayed the invocation of ' recovernames () ' in line 14th. When the ' fullName ' occurs panic, the delay function ' recovername () ' is called, which uses ' Recover () ' To stop the Panic continuation event. The program outputs: "' Recovered from runtime Error:last name cannot is nil returned normally from main deferred" in main "when the program is in the The delay function ' recovername ' is called when the panic occurs in line 19, which in turn invokes ' recover () ' to regain control of the panic. Line 8th calls ' recover ', returns the ' panic ' argument, and therefore prints: ' Recovered from runtime Error:last name cannot is nil ' after executing ' recover () ', p The anic will stop, the program control returns to the caller (here is the ' main ' function), and after the panic occurs, it will continue to run normally from line 29th. The program prints ' returned normally from main ', followed by ' deferred call in main '. # # Panic,recover and go will only work if you call recover in the same [go coprocessor] (https://studygolang.com/articles/12342). ' Recover ' cannot recover a panic of a different co-process。 We use an example to understand this. "' Gopackage mainimport (" FMT "" Time ") func recovery () {if r: = Recover (); r! = nil {fmt. Println ("Recovered:", R)}}func a () {defer recovery () fmt. Println ("Inside A") go B () time. Sleep (1 * time. Second)}func B () {FMT. Println ("Inside B") Panic ("oh! B panicked ")}func main () {a () fmt. PRINTLN ("Normally returned from main")} ' [Run on Playground] (Https://play.golang.org/p/pEVzTLz36Y) in the above program, function ' B () ' In 23 rows occur panic. The function ' A () ' calls a delay function ' recovery () ', which is used to restore panic. In line 17th, the function ' B () ' is called as a different thread. The next line of ' Sleep ' only guarantees that ' a () ' Exits after the ' B () ' Run is finished. What do you think the program will output? Can panic recover? The answer is no, panic will not recover. It is not possible to recover panic because the panic that occur in the recovery and ' B () ' are not the same. Running the program will output: "' Inside A Inside B panic:oh! B Panickedgoroutine 5 [Running]: main.b ()/tmp/sandbox388039916/main.go:23 +0x80created by main.a/tmp/sandbox388039916 /main.go:17 +0xc0 "from the output can be seen, panic not recovered. If the function ' B () ' is called in the same coprocessor, the panic can be restored. If the 17th line of the program is modified by ' Go B ' () to ' B () ', the panic can be restored because panic occurs in the same process as recover. If you run this modified program, it will output: "' Inside A Inside B recovered:oh! B panicked normally returned from main "# # Run time Panic run-time errors (such as array out of bounds) also cause panic. This is equivalent to calling the built-in function ' panic ', whose parameters are determined by the interface type [runtime. Error] (https://golang.org/src/runtime/error.go?s=267:503#L1). ' Runtime. The error ' interface is defined as follows: ' ' Gotype Error interface {error//RuntimeError is a no-op function but//serves to distinguish types th At was run time//errors from ordinary errors:a type was a//run time error if it has a RuntimeError method. RuntimeError ()} ' and ' Runtime. The error ' interface satisfies the built-in interface type [' ERROR '] (https://golangbot.com/error-handling/#errortyperepresentation). Let's write an example to create a run-time panic. "' Gopackage mainimport (" FMT ") func A () {n: = []int{5, 7, 4} FMT. Println (N[3]) fmt. PRINTLN ("Normally returned from a")}func main () {a () fmt. PRINTLN ("Normally returned from main")} ' [Run on Playground] (https://play.golang.org/p/CBsK2xXzGg) in the above program, line 9th we tried to access ' n[3] ', which is an error reference to [slice] (https://studygolang.com/articles/12121). The program will occur panic, output as follows: "' Panic:runtime error:index out of Rangegoroutine 1 [running]: Main.a ()/tmp/sandbox780439659/main.go:9 +0x40main.main ()/tmp/sandbox780439659/main.go:13 +0x20 "You might want to know if you can restore a runtime panic? Of course! Let's revise the above code to restore the panic. "Gopackage mainimport (" FMT ") func R () {if r: = Recover (); r! = nil {fmt. Println ("recovered", R)}}func a () {defer R () N: = []int{5, 7, 4} FMT. Println (N[3]) fmt. PRINTLN ("Normally returned from a")}func main () {a () fmt. PRINTLN ("Normally returned from main")} "[Run on Playground] (HTTPS://PLAY.GOLANG.ORG/P/QUSVZE5RFT) run the above program will output:" Recovered runtime Error:index out of a range normally returned from main "from the output can be known that we have restored this panic. # # Get a stack trace after recovery when we recover panic, we release its stack trace. In fact, in the above procedure, after recovering panic, we lost the stack trace. There is a way to print out the stack trace, which is to use [' Printstack ' in the [' Debug '] (https://golang.org/pkg/runtime/debug/) package (https://golang.org/pkg/ runtime/debug/#PrintStack) function. "' Gopackage mainimport (" FMT "" Runtime/debug ") func R () {if r: = Recover (); r! = nil {fmt. Println ("recovered", r) Debug. Printstack ()}}func A () {defer R () N: = []int{5, 7, 4} FMT. Println (N[3]) fmt. Println ("Normally retUrned from a ")}func main () {a () fmt. PRINTLN ("Normally returned from main")} ' [Run on Playground] (Https://play.golang.org/p/D-QlDmumHV) in the above program, we are in the 11th The line uses ' Debug '. Printstack () ' Prints the stack trace. The program outputs: "' Recovered runtime Error:index out of range Goroutine 1 [running]: Runtime/debug. Stack (0x1042beb8, 0x2, 0x2, 0x1c)/usr/local/go/src/runtime/debug/stack.go:24 +0xc0runtime/debug. Printstack ()/usr/local/go/src/runtime/debug/stack.go:16 +0X20MAIN.R ()/tmp/sandbox949178097/main.go:11 +0xe0panic (0XF0A80, 0X17CD50)/usr/local/go/src/runtime/panic.go:491 +0x2c0main.a ()/tmp/sandbox949178097/main.go:18 + 0x80main.main ()/tmp/sandbox949178097/main.go:23 +0x20normally returned from main "from the output we can see that the first has been restored panic, print out ' Recovered runtime Error:index out of range '. In addition, we also printed out the stack trace. After recovering the panic, the ' normally returned from main ' is also printed. This concludes the tutorial. Briefly summarize what is discussed in this tutorial:-What is panic? -When should I use panic? -panic example-defer-recover-panic,recover and Go panic at the time of the runtime-run-time panic-recovery after getting stack trace I wish you a pleasant stay. * * Previous tutorial-[Custom ERROR] (https://studygolang.com/articles/12784) * * * * Next tutorial-[prime Function] (https://studygolang.com/articles/12789) * *

via:https://golangbot.com/panic-and-recover/

Author: Nick Coghlan Translator: Noluye proofreading: polaris1119

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

2015 reads

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.