This is a creation in Article, where the information may have evolved or changed.
In many object-oriented languages such as Java or PHP, exception handling is dependent on throw, catch. In the go language, the panic and recover functions are equal to the throw and catch statements respectively at the action level, and of course there are differences.
From the design level, the panic and recover functions apply to those real exceptions (such as integers except 0), while the throw catch-finally mechanism is often used to handle some custom exceptions at the business level. So in the go language, panic and recover should be used with caution.
In the use of these two abnormal mechanisms, the trend of handling anomalies is 控制流程
similar.
The following examples illustrate each of:
Try Catch finally mechanism
try{ throw new Exception(); } catch(Exception $e) { do something ... } finally { }
In this mechanism, we put the statement that could throw the exception or the statement that throws the custom exception into the TRY statement block, and in the catch block, we take the exception caught by the above statement, alarm or log for different exceptions. After that, the control flow enters into the finally statement block. Without a finally statement, the control flow enters the statement after the catch. In other words, in this mechanism, the control flow is transferred to the statement after the exception capture in the same level.
Panic Recover defer mechanism
In the go anomaly mechanism, panic can break the original control flow and enter into a "panic" process. This panic process can be explicitly invoked either by the panic () function or by a run-time error (such as an array subscript for access beyond the bounds). Panic in the function that calls it to this layer and all of its upper level is thrown, if there is no recover to capture it, the program exits will produce crash, if in a layer defer statement is recover captured, the control process will go into the statement after recover.
/* example 1 */ package main import ( "fmt" ) func f() { defer func() { fmt.Println("b") if err := recover();err != nil { fmt.Println(err) } fmt.Println("d") }() fmt.Println("a") panic("a bug occur") fmt.Println("c") } func main() { f() fmt.Println("x") }
In the example above, the output is:
a b a bug occur d x
This shows that the panic thrown in the F function is captured by recover in its own defer statement, and then the control flow enters the statement after the recover, that is, print d, print x, and then the process exits normally.
/* example 2 */ package main import ( "fmt" ) func g() { defer func() { fmt.Println("b") if err := recover();err != nil { fmt.Println(err) } fmt.Println("d") }() f() fmt.Println("e") } func f() { fmt.Println("a") panic("a bug occur") fmt.Println("c") } func main() { g() fmt.Println("x") }
The output of the above case is:
a b a bug occur d x
The process goes through a process where the panic is thrown in F (), and panic is thrown into G () because it does not define the defer statement itself. The defer statement in G () defines the recover, captures the panic and executes the defer remaining statements, after which the control flow is transferred to the main () function until the end of the process.