Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It's the same principle as parsing. Database work involves lots of querying, scanning, etc. All of these operations produce errors. In the work that I do, the response to an error is usually, "rollback, show error to user." This makes it ideal for panic/recover. (And this can work well for either command line applications or web applications.)


Panicking isn't done when a database operation fails. Returning an error value is. It's just like old-school C. Panics are for programming errors or things like out of memory conditions, not errors in ordinary operation, even when components are failing.


Exactly.

I have exactly two panics in my ~15k line server. Both are in initialization code that will probably never get called, so it will fail very early on in the code. The rest of my code looks like this:

    func getRecord(args...) (err error) {
        if err := doSomethingRisky(); err != nil {
            return err
        }
        if err := doSomethingElseRisky(); err != nil {
            return err
        }
        ... other code ...
        return nil
    }

    func processRecord() error {
        if err := getRecord(args...); err != nil {
            return err
        }
        ... do other stuff ...
        return nil
    }
All the way down the stack. It's certainly a little more code, but it forces you to at least acknowledge all errors. If you want a stack-trace, you can always use the runtime package.


No, this isn't what I'm talking about. See my response: https://news.ycombinator.com/item?id=7222197


I hate to be rude, but I feel like you jumped into this thread without reading the context.

I'm not talking about panicing instead of returning errors. I'm talking about using an idiom---which is used in the Go standard library (see my link up-thread)---to make error handling more terse when you're working with code that is otherwise profligate with checking errors.

At no point is a panic exposed to the user of a program or to the client of a library. At no point are errors ignored. The panics are kept within package and converted to error values.


Guarding your library boundary with a recover doesn't absolve your library internals from being nonidiomatic by using panics. (That the stdlib uses panic/recover in a few specific places does not make it broadly idiomatic.)

Without seeing specific code I can't say for sure, but it's very unlikely that any database interaction code is best modeled with panic/recover for error handling. I'm very curious to see the source, at this point.


> Guarding your library boundary with a recover doesn't absolve your library internals from being nonidiomatic by using panics.

Using panic/recover doesn't automatically make your code nonidiomatic.

> (That the stdlib uses panic/recover in a few specific places does not make it broadly idiomatic.)

That the stdlib uses panic/recover in several places is a good indicator that "never use panic/recover" is bad advice. Note that while I agree that just because something is in the stdlib doesn't mean it's idiomatic, I also cite that this particular approach is used to make the structure and organization of code more clear. Since it's used in several packages, I claim that this is a strong hint that panic/recover is appropriate in limited scenarios.

> Without seeing specific code I can't say for sure, but it's very unlikely that any database interaction code is best modeled with panic/recover for error handling. I'm very curious to see the source, at this point.

It's really not that hard to imagine. For example: http://play.golang.org/p/fhpRLd8EHY

We seem to have some wires crossed. Let's be clear, shall we?

* The panic/recover idiom is rarely used, but it is an idiom.

* There are trade-offs involved with using panic/recover. In my sample linked in this comment, many of the functions in database/sql need to be stubbed out so that they panic. However, the cost of this is relatively small, since it can mostly be isolated in a package.

* The idiom is most frequently seen in parsing because there are a lot of error cases to handle and the response to each error is typically the same.

* While parsing is the common scenario, I claim it is not the only one. I cite that database work is profligate with error checking, and depending on your application, there's a reasonable chance that the response to each error is going to be the same. When doing a lot of it, it can pay off to use the panic/recover idiom with similar benefits as for doing it with parsing.

* There may well be other scenarios where such handling is appropriate, but I have not come across them.

I've done an unusual amount of work with parsers and have done some database work, so I've had the opportunity to bump up against the panic/recover idiom a bit more than normal. As with anything else, it can be abused. But I find it extraordinarily useful in certain situations.


I've fixed some compile errors in my code snippet: http://play.golang.org/p/PLyMAD5ZvG --- sorry about that.


This is just another example of Go's fundamental attitude. Stuff is available for the language designers, but not for you :

* generic functions (e.g. append)

* generic data types (e.g. slices)

* exceptions (like illustrated above)

* special case syntax

* Custom event loops

* precompiler macros (very bad to use, horrible, blah blah ... except of course for the people imposing this restriction, and YES they're using it amongst other things to workaround the lack of generics in C)

...

This attitude was common in middle-90s "generic" programming languages like Ocaml, Modula-2 and others. You should simply look at Go as one of those languages and treat it as such.

If this attitude bothers you, you should look at C++0x and D.


I've read your comment twice and I cannot see any pertinent connection between it and what I said.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: