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

The practical difference is that there is (partial) enforced checking of errors. If you do not wish to check the error code, you must be explicit.

    f := os.Create("output.txt")
Will give a compile error

    multiple-value os.Create() in single-value context:
and should be written as one of these:

    f, err := os.Create("output.txt")
    f, _ := os.Create("output.txt")
where the second indicates that you are ignoring the returned error.

I say "partial" because if you ignore all the return values you can implicitly ignore an error:

    fmt.Println("Hello")
It is quite common to see:

    if err != nil {
        //handle error
    }
in Go, as their philosophy is that the caller should handle the error, not an unrelated piece of code. Yes, this does sometimes look like "litter", and it doesn't really make for the most impressive code. However, you won't be surprised by it, it's simple to understand, and if something goes wrong, you'll know what, when, and what was done about it. This has been Google's opinion on C++ for a while. http://google-styleguide.googlecode.com/svn/trunk/cppguide.x... lists some pros and cons. Writing code that ignores errors is one way of writing code, I think it's idiomatic Java and Python (please correct me), but that's not the way that was chosen for Go.

I don't really use panic() except to indicate bugs:

    if playerCount == 2{
        go multiPlayer()
    } else if playerCount == 1{
        go singlePlayer()
    } else {
        panic(playerCount)
    }
However they can be useful inside libraries. For example if you call fmt.Printf("%s",s), where s has a method s.String(), will print the result of s.String(). Sound good? But what if s is a nil pointer? Well, you may wish s.String() to handle that and return "A nil s", which is fair enough. However is s.String does not handle this case it may panic(), leaving fmt.Printf to recover() and write "<nil>" instead.

http://golang.org/src/pkg/fmt/print.go#L630



For me it's very common to defer error handling. For instance I'm logging most runtime errors and later I receive a nice report over email. I then click on the links provided and I get nice call-stack traces. I then go and fix those errors.

And while it would have been better to treat those errors in the first place, we do know that's not possible and trying to force the developers only leads to code such as ...

    try {
       ...
    } catch(Exception ex) {}
Checkout this piece on checked exception, also by a Google employee:

http://googletesting.blogspot.ro/2009/09/checked-exceptions-...


This doesn't sit well with me. Who is to say what's catastrophic and what's not? Should I use all libraries in fear because passing a nil pointer or an improperly formatted date may cause it to terminate the program with no recourse? Suddenly every library is a ticking time bomb with a scorched Earth policy for things it doesn't like. How am I to know what's going to cause my valuable program to simply die in the middle of the night? Look at the outdated/incomplete documentation? Pore over the complex code (if it's even available)? Now not only do I need to litter error value checks everywhere, but I also need to preemptively sanitize all input to any library calls I make and pray that I haven't missed something. This is simply trading one problem for another.


That's a potential issue with any language, I believe. In Go you can recover() from what would otherwise be a termination. For example, I have a function that grabs and parses RSS feeds. If my program is fed junk by the remote site, I don't want to terminate, I want to ignore the error for that feed (after logging it). To do this I recover() from any error at the feed level.


Is your opinion set by the article's assertion "panics are always fatal"? Because that is incorrect, there are good mechanisms for handling them.


And to think what they could have done if they'd ever heard of the Exception Monad.


> If you do not wish to check the error code, you must be explicit.

Or you can ignore all the return values, like in your fmt.Println() example.

> I say "partial" because functions that only return 1 value can ignore the return implicitly:

fmt.Println() returns two values, one of which is of the error type. You can't ignore just one of those values, but you can ignore both of them.


Correct. Thank you.




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

Search: