Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching panics in Golang

With the following code, if no file argument is given, a panic is thrown for line 9 panic: runtime error: index out of range as expected.

How can I 'catch' this panic and handle it when directly when passing something to it (os.Args[1]) that causes the panic? Much like try/catch in PHP or try/except in Python.

I've had a search here on StackOverflow but I've not found anything that answers this as such.

package main  import (     "fmt"     "os" )  func main() {     file, err := os.Open(os.Args[1])     if err != nil {         fmt.Println("Could not open file")     }     fmt.Printf("%s", file) } 
like image 349
Luke B Avatar asked Jul 29 '14 21:07

Luke B


People also ask

How do you catch panics in Golang?

Recover is a function provided by Go which takes control of a panicking goroutine. recover() can only be used inside deferred functions. If you call recover() during normal flow, it will simply return nil . However, if a goroutine is panicking, recover() will capture the panic value.

How do you deal with panic in Go lang?

A panicking program can recover with the builtin recover() function: The recover function allows a program to manage behavior of a panicking goroutine. Suppose a function G defers a function D that calls recover and a panic occurs in a function on the same goroutine in which G is executing.

Should you panic in Golang?

Don't use panic for normal error handling. Use error and multiple return values. See https://golang.org/doc/effective_go.html#errors.

What happens when Go routine panics?

A panic is an exception in Go A panic stops the normal execution of a goroutine: When a program panics, it immediately starts to unwind the call stack. This continues until the program crashes and prints a stack trace, or until the built-in recover function is called.


1 Answers

A panicking program can recover with the builtin recover() function:

The recover function allows a program to manage behavior of a panicking goroutine. Suppose a function G defers a function D that calls recover and a panic occurs in a function on the same goroutine in which G is executing. When the running of deferred functions reaches D, the return value of D's call to recover will be the value passed to the call of panic. If D returns normally, without starting a new panic, the panicking sequence stops. In that case, the state of functions called between G and the call to panic is discarded, and normal execution resumes. Any functions deferred by G before D are then run and G's execution terminates by returning to its caller.

The return value of recover is nil if any of the following conditions holds:

  • panic's argument was nil;
  • the goroutine is not panicking;
  • recover was not called directly by a deferred function.

Here is an example of how to use this:

// access buf[i] and return an error if that fails. func PanicExample(buf []int, i int) (x int, err error) {     defer func() {         // recover from panic if one occured. Set err to nil otherwise.         if (recover() != nil) {             err = errors.New("array index out of bounds")         }     }()      x = buf[i] } 

Notice that more often than not, panicking is not the right solution. The Go paradigm is to check for errors explicitly. A program should only panic if the circumstances under which it panics do not happen during ordinary program executing. For instance, not being able to open a file is something that can happen and should not cause a panic while running out of memory is worth a panic. Nevertheless, this mechanism exists to be able to catch even these cases and perhaps shut down gracefully.

like image 181
fuz Avatar answered Sep 30 '22 18:09

fuz