text
It is well known that the recover function in golang can catch panic to prevent the entire service from being unavailable in the event of an exception. However, in some cases, recover cannot catch panic. Here are some of these situations.
1. Under normal circumstances
package main import "fmt" func main(){ defer func(){ if err := recover();err != nil{ ("err = %v",err) } }() panic("a panic") } Print results: err = a panic Process finished with exit code 0
Can catch panic normally
2. Goroutine panic
Previously, the online environment had panic interfaces, which made the service unavailable, so my colleague directly added a recovery to the main function and thought that everything was worry-free. In fact, recover cannot catch panics in coroutines.
package main import "fmt" func main(){ defer func(){ if err := recover();err != nil{ ("err = %v",err) } }() go func(){ panic("a panic") }() select{} } Print results: panic: a panic goroutine 6 [running]: .func2() I:/goProject/:13 +0x40 created by I:/goProject/:12 +0x5e
In fact, panic will still cause the service to be unavailable.
Correct writing
package main import "fmt" func main(){ go func(){ defer func(){ if err := recover();err != nil{ ("err = %v",err) } }() panic("a panic") }() select {} } Return value: fatal error: all goroutines are asleep - deadlock! goroutine 1 [select (no cases)]: () I:/goProject/:15 +0x41 err = a panic Process finished with exit code 2
You can see that the panic is caught normally, and because the select statement is blocked, a deadlock error was reported.
3. Indirect call recovery
When I wanted to encapsulate the recover into a function, I found that the recover did not take effect, because the recover will only take effect when it is called directly by the defer statement. Panic cannot be captured correctly when recover is inside other functions.
package main import "fmt" func main(){ defer cover() panic("a panic") } func cover(){ defer func(){ if err := recover();err!= nil{ (err) } }() } Return value: panic: a panic goroutine 1 [running]: () I:/goProject/:7 +0x62
4. nil panic
To be captured, a condition needs to be met, that is, panic is not nil panic, otherwise it is impossible to know whether panic has not occurred or panic itself is nil when making capture judgments.
For example, the following code
package main import "fmt" func main() { defer func(){ if err := recover();err != nil{ (err) } ("after recover") }() panic(nil) select{} } Return value: after recover
Recover does not handle the exception correctly because the value of the exception is nil.
Five, summary
This article tells the story of three types of recovery failure.
- Panic appears in Ctrip
- Defer does not call recover directly
- The value of panic is nil
When writing code, you need to pay attention to avoid the service being unavailable due to these situations. The above are some pitfalls that golang novices often encounter.
The above is the detailed content of some pitfalls in the use of golang recover function. For more information about golang recover function pitfalls, please pay attention to my other related articles!