Panic and recovering

Go does not have an exception mechanism: you cannot throw exceptions. Instead ituses a panic-and-recover mechanism. It is worth remembering that you should usethis as a last resort, your code will not look, or be, better if it is litteredwith panics. It’s a powerful tool: use it wisely. So, how do you use it? In thewords of the Go Authors [go_blog_panic]:

  • Panic
  • is a built-in function that stops the ordinary flow of control and beginspanicking. When the function F calls panic, execution of F stops, anydeferred functions in F are executed normally, and then F returns to itscaller. To the caller, F then behaves like a call to panic. The processcontinues up the stack until all functions in the current goroutine havereturned, at which point the program crashes. Panics can be initiated byinvoking panic directly. They can also be caused by runtime errors, such asout-of-bounds array accesses.
  • Recover
  • is a built-in function that regains control of a panicking goroutine.Recover is only useful inside deferred functions. During normal execution,a call to recover will return nil and have no other effect. If the currentgoroutine is panicking, a call to recover will capture the value given topanic and resume normal execution.

This function checks if the function it gets as argument will panic when it isexecuted10:

  1. func Panic(f func()) (b bool) { 1
  2. defer func() { 2
  3. if x := recover(); x != nil {
  4. b = true
  5. }
  6. }()
  7. f() 3
  8. return 4
  9. }

We define a new function Panic 1 that takes a function as an argument (see). It returns true if f panics when run, else false. Wethen 2 define a defer function that utilizes recover. If the currentgoroutine panics, this defer function will notice that. If recover() returnsnon-nil we set b to true. At 3 Execute the function we received as theargument. And finally 4 we return the value of b. Because b is a namedreturn parameter.

The following code fragment, shows how we can use this function:

  1. func panicy() {
  2. var a []int
  3. a[3] = 5
  4. }
  5. func main() {
  6. fmt.Println(Panic(panicy))
  7. }

On line 3 the a[3] = 5 triggers a runtime out of bounds error which resultsin a panic. Thus this program will print true. If we change line 2: vara []int to var a [4]int the function panicy does not panic anymore. Why?