Go panic: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
=Internal=
=Internal=
* [[Go_Language_Error_Handling#panic|Go Language Error Handling]]
* [[Go_Language_Error_Handling#panic|Go Language Error Handling]]
=Recovering after a Panic=
If a function panics, a function executed with <code>defer</code> after the function that panicked can retrieve the argument <code>panic()</code> was called with an restore the normal flow of the program.
<syntaxhighlight lang='go'>
func main() {
defer aRecoveryFunc()
aFuncThatPanics()
}
func aFuncThatPanics() {
fmt.Printf("before panicking ...\n")
panic(fmt.Errorf("I panicked"))
}
func aRecoveryFunc() {
r := recover()
if r == nil {
fmt.Printf("nobody panicked")
} else {
// r is the error the panic was called with
        err := r.(error)
fmt.Printf("I recovered this: %s\n", err.Error())
}
}
</syntaxhighlight>
The result:
<syntaxhighlight lang='text'>
before panicking ...
I recovered this: I panicked
</syntaxhighlight>
=TO PROCESS=
<font color=darkkhaki>
Read and integrate:
* https://go.dev/ref/spec#Run_time_panics
* https://go.dev/ref/spec#Handling_panics
* https://go.dev/blog/defer-panic-and-recover
* https://gabrieltanner.org/blog/golang-error-handling-definitive-guide/#defer-panic-and-recover
* https://learning.oreilly.com/library/view/100-go-mistakes/9781617299599/OEBPS/Text/07.htm#heading_id_3
Understand this pattern:
<syntaxhighlight lang='go'>
  if err := http.ListenAndServe(":8082", nil); err != nil {
      panic(err)
  }
</syntaxhighlight>
=Overview=
=Overview=


<font color=darkkhaki>
 
Use panics in truly exceptional cases.
Use panics in truly exceptional cases.



Latest revision as of 01:16, 15 March 2024

Internal

Recovering after a Panic

If a function panics, a function executed with defer after the function that panicked can retrieve the argument panic() was called with an restore the normal flow of the program.

func main() {
	defer aRecoveryFunc()
	aFuncThatPanics()
}

func aFuncThatPanics() {
	fmt.Printf("before panicking ...\n")
	panic(fmt.Errorf("I panicked"))
}

func aRecoveryFunc() {
	r := recover()
	if r == nil {
		fmt.Printf("nobody panicked")
	} else {
		// r is the error the panic was called with
        err := r.(error)
		fmt.Printf("I recovered this: %s\n", err.Error())
	}
}

The result:

before panicking ...
I recovered this: I panicked

TO PROCESS

Read and integrate:

Understand this pattern:

  if err := http.ListenAndServe(":8082", nil); err != nil {
      panic(err)
  }

Overview

Use panics in truly exceptional cases.

A panic indicates a programmer error (attempting to access an array index out of bounds, writing an uninitialized map, etc.). Panics can also be triggered with:

panic(<message>)

The panic can be caught on the stack outside the function that caused the panic, by executing recover(). Recover can be called in any upper function on the stack, or even if the function that triggers the panic, if the invocation is made with defer.

The recover() built-in function allows a program to manage behavior of a panicking goroutine. Executing a call to recover inside a deferred function, but not any function called by it, stops the panicking sequence by restoring normal execution and retrieves the error value passed to the call of panic. If recover is called outside the deferred function it will not stop a panicking sequence. In this case, or when the goroutine is not panicking, or if the argument supplied to panic was nil, recover returns nil. Thus the return value from recover reports whether the goroutine is panicking.