Go panic / recover (try / except)

Hi,

so as I learn little by little to understand Go, my primary experience is with Python so I naturally want to do things like

try:
    ... do stuff ...
except Exception as e:
    ... logger.error("something bad happened: {0}".format(e)) ...

and this is somewhat possible in Go with defer and a anonymous function

defer func() {
	if err := recover(); err != nil {
		fmt.Println("recover:", err)
		return
	}
}()
panic(1)
fmt.Println("after panic")

however, the above Python example actually allows for the application to continue, but Go doesn’t ?

output> recover: 1

why wouldn’t it return and keep going in the program ?

Thanks!
Alex

Go does not have exceptions, panic is not throw, recover is not catch.

Hi Dave, I guess it’s a matter of how things are meant to be done in Go - the above example came up because I was trying to do a http.Get but that all for whatever reason failed (e.g. Typo in protocol htttp instead of http) and ended up in a panic which then stopped continuing the program.

How do I continue in this case? Http.Get panicked but I don’t want to make that exit my program, I want to deal with it and/or continue …

Many thanks!
Alex

Errors happen. You must accept this as the norm and write your program with the assumption that most of the time, nothing works.

At a practical level this means writing your program to be tolerant if it is restarted in an unclean state due to a hard termination, and to place your program under a process manager that will restart it if it exits unexpectedly.

At a guess, http.Get did probably not panic, but you may have tried to use it’s response return without first checking the error return. In Go, you always check errors first, when they are returned by the function you are calling.

Hi Dave,

Ok I understand that, but if I was to feed a program say a list/array/slice of URLs and one was faulty (protocol example) and I loop over that array, how would I let Go continue and ignore / deal with the error/panic the one URL caused?

Thanks for bearing with me! :slight_smile:
Alex

We posted simultaneously, but to explicitly answer your question: you check the error return from http.Get for each call. There should be no panics or recovers involved in this flow.

Hi Jakob / Dave -

you’re correct http.Get actually returns a list (response, error) - and I seem to be able to deal with that :+1: … i tried the same using a http.Client{} type/object and that didn’t go so well … here’s what I tried :
https://play.golang.org/p/iQd4FCd91B

event though I should get a error type/object back:
181 func (c *Client) Do(req *Request) (*Response, error) {

maybe client.Do isn’t meant to be used like that, but I’ve seen it in some / many examples, e.g.
http://stackoverflow.com/a/24455606

Thanks for all your help!
Alex

        resp, err := http.Get(list_of_urls[url])
		if err != nil {
			fmt.Println("do stuff with the err: ", err)
		}
		if resp != nil {
			fmt.Println(resp)
		}

If you do get an error here, you’ll anyway proceed to processing resp, which you usually should not. http.Do seems to have some valid cases where it returns an error and a non-nil response, and those special cases are fine but untypical. In idiomatic Go, you should not even glance att the result if the error return is non-nil; the other value is essentially undefined unless documented otherwise, and may be nil or may be non-nil but anyway invalid.

The same further down in your example. You typically want somehing like

result, err := some.Operation(...)
if err != nil {
    // handle the error, by printing, retrying or whatever is appropriate
    // continue, break or return depending on the context
}
result.Something() // never get here if err != nil
1 Like

is there a page that would give some guidance on idiomatic Go ? :slight_smile: would be great to have a read while i’m learning :slight_smile:

also, thanks the continue did what I would have expected … however, that wouldn’t work if I wasn’t in a loop though, but maybe not looping would not be idiomatic …

thanks for your help, that all makes much more sense now :thumbsup:
Alex

Dave, who responded above, has a nice list of resources that all deal with idiomatic Go in one way or the other:

http://dave.cheney.net/resources-for-new-go-programmers

If you were not in a loop you would have perhaps have been in a function or method call, in which case you would have returned - maybe the same error to the caller, and let them continue there, or maybe an error decorated with more detail. And so on - the appropriate response to the error depends on the context, but the one constant is that if you got a result, err pair and the err was non-nil, you do not process the result.

Unless you’re in one of the specific cases where it’s documented that you should process the result even in the case of an error. But that’s still the general rule.

cool - thanks very much Jakob (and Dave) :slight_smile:

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.