Let’s revisit exception handling in Golang 😸

  • 1.Golang is not found in other languagestry... catch...Statement to catch exceptions and exception recovery
  • 2. We usually use GolangpanicKeyword to throw an exception indeferThe use ofrecoverTo catch exceptions for specific logical processing
  • 3. In Golang we usually return in a function or methoderrorStructure object to determine if an exception occurs

Matters needing attention

  • 1. The use ofrecoverandpanicInstructions,deferMust be defined before panic (Panic terminates subsequent code execution).
  • 2.recoverOnly in thedeferIs valid only in the function called, otherwiserecoverUncapturepanic.
  • 3.recoverAfter handling the exception, the business logic runs todeferLater in the processing fragment
  • More than 4.deferWill form theDefer the stack
  • 5. Panic will wait until the wholegoroutineAn error is reported only when you exit

Routine use of

  1. panicAs well asrecoverParameter type is empty interface (can store objects of any type)interface{}
/* func panic(v interface{}) func recover() interface{} what can I ask? Panic. Explain: */ package main import (" FMT ") func main() {defer func() {if err := recover(); err ! = nil { fmt.Println(err) } }() panic("oh my god! panic.") }Copy the code

  1. Errors raised in deferred calls can be caught by subsequent deferred calls (Only the last error was caught)
/* Defer anonymous function with panic()-> defer anonymous function with recover() Recover in defer can only catch the last error package main import (" FMT ") func main() {defer func() {if err := recover(); err ! = nil { fmt.Println("catch the panic") } }() defer func() { panic("oh my god! panic.") }() panic("something panic!" )}Copy the code

  1. Capture functionrecover()Only in thedeferA direct call within the call terminates, otherwise returnsnil
/* The code is implemented in the following order :panic-> nest the recover defer function in the anonymous function -> FMT defer-> recover defer-> call the recover defer function in the anonymous function: Defer inner <nil> defer recover panic error The third defer printed 'nil' of Recover (), Only the first defer successfully captured the bottom panic("panic error") */ package main import "FMT" func main() {defer func() {fmt.println ("defer recover",recover()) }() defer recover() defer fmt.Println(recover()) defer func() { func(){ fmt.Println("defer inner") recover() }() }() panic("panic error") }Copy the code

  1. Placing code blocks in anonymous functions enables exception recovery within the function logic without affecting the main function
/* Defer defer defer defer defer defer defer defer defer defer defer defer defer 2 explanation: Panic will terminate subsequent execution, so panic in the anonymous function will be executed first, and recover in defer will be captured, and I will be assigned to 2. */ package main import "FMT" func main() {test()} func test() {var I int func() {var I int func() { defer func(){ if err := recover(); err ! = nil { i = 2 } }() panic("something panic!" ) i += 8 fmt.Println("no panic, i is:",i) }() fmt.Println("i is:",i) }Copy the code

  1. The recover goroutine

Note: If a panic occurs in a Goroutine that is not recovered, the entire process will die

/ * WaitGroup is used to Wait for the end of a set of goroutines,Add is used to set the number of goroutines to Wait, and Done is used to indicate the end of a goroutine.Wait is used to block all goroutines until all goroutines are executed -> Wg.wait ()-> FMT.Println panic recover Assignment to entry in nil map donw In goroutine we declare a map[string]string of info. We know that map,slice, and channel are all reference types that need to be initialized by make. The assignment directly using info["name"] = "BGBiao" causes panic, and the fmt.println function is terminated, so defer with Recover is executed. Then defer with Wg.done () and exit Goroutine to execute the main program logic */ package main import (" FMT ""sync") func main() {var wg sync.waitgroup wg.Add(4) go func() { defer wg.Done() defer func() { if err := recover(); err ! = nil { fmt.Println("panic recover",err) } }() var info map[string]string info["name"] = "BGBiao" fmt.Println(info) }() wg.Wait() fmt.Println("done") }Copy the code

Welcome to follow my official account: BGBiao, progress together ~