Live data from Hacker News

Why I’m not leaving Python for Go

uberpython.wordpress.com

61–70 of 245 posts

Re: Why I’m not leaving Python for Go

#61

If you use a language that uses error codes, then you're forced to explicitly think about what to do in every single error case (or not, and accept the consequences). This can add a lot of mental overhead, but can result in a much more robust and well-thought-out program. But because more logic is involved period (to handle the robustness), the program is necessarily more complex. If you use exception handling, then…

"Of course, you can add more code to deal individually with each of the exceptions in more robust ways, even to the point of wrapping each statement in its own try/catch block, but then it's no different in practice from returning error codes." It is very different. With a try/catch block, you can see the normal logic flow of your code in one place, separated from the error handling logic. If you wrap each and every…

Um... errors ARE normal operation. Consult historical output from your C++ compiler, if you don't believe me!

(If anything, that should probably be "errors", quotes included, because what people usually mean by the term is "easily-forseeable occurrence that I couldn't be bothered to write the code for".)

Re: Why I’m not leaving Python for Go

#62

If you use a language that uses error codes, then you're forced to explicitly think about what to do in every single error case (or not, and accept the consequences). This can add a lot of mental overhead, but can result in a much more robust and well-thought-out program. But because more logic is involved period (to handle the robustness), the program is necessarily more complex. If you use exception handling, then…

I basically agree with you. I think return codes are simpler, and exceptions appear simpler because we're used to them. In reality they are a magical, out-of-band mechanism compared to plain old return. I contend that local and explicit is more strongly correlated with simplicity than remote and implicit.

Put another way, verbose code can be simpler if it is direct and explicit — what happens is what's on the page — just as succinct code can be more complex if it is magical or implicit — what actually happens depends on who is calling it, say.

Re: Why I’m not leaving Python for Go

#63
post #29

I'm not in love with this aspect of Go either, and I also find that the idiom for dealing with it (multiple return values and multi-statement if conditional clauses) doesn't play well with Go's scoping rules, so that I find myself regularly having to decide between cleaner conditional or an explicit variable declaration. I also don't love how it makes my code look like my teenage-years C code. But I also think this i…

What a refreshingly even-handed perspective. And you even talk about semantics instead of syntax.

Go isn't particularly elegant in my opinion, either, at least not compared to a lot of languages. But it's pretty good for getting stuff done, and handles a lot of common problems in a way that is direct and simple. I can perceive that utilitarianism as a form of elegance.

Re: Why I’m not leaving Python for Go

#64

If you use a language that uses error codes, then you're forced to explicitly think about what to do in every single error case (or not, and accept the consequences). This can add a lot of mental overhead, but can result in a much more robust and well-thought-out program. But because more logic is involved period (to handle the robustness), the program is necessarily more complex. If you use exception handling, then…

Joel Spolsky on exceptions : http://www.joelonsoftware.com/items/2003/10/13.html

Re: Why I’m not leaving Python for Go

#65
post #44

On the topic of when to use error-returns vs. when to use panic: I struggled with this aspect of Go coding too and what I decided was that, in order to choose your approach to errors, you should think about how important it is that your function can be composed into an expression: x := foo(a) + bar(b) vs. c, err := foo(a) if err != nil { ... } d, err := bar(b) if err != nil { ... } x := c + d It's a trade-off. By usi…

As I understand it, it is about severity. I think "panic" and "error" are meant to handle situations where there is no obvious, correct answer, like with array indexing. A nil pointer is another gimme example. Some languages have unchecked exceptions — maybe conceptualize it somewhat like that. panics() are for disasters, for serious program errors.

By contrast, a network timeout is not a disaster. It's not "normal" or desired behavior but it's well within widely-known modes of behavior.

Composition is nice-to-have but in general you ought to be able to write Go as if everything that does not return errors will succeed under the vast majority of circumstances, or where failure is inevitable.

Recover is, among other things, a failsafe of sorts for cases when code you do not control (e.g. a library) panics. It might be catastrophic failure for the library, but it may not be for your code, and you need an escape hatch.

...I am not an expert, either, but I've spent a fair amount of time on the Go mailing lists. I feel like I'm actually repeating something I've read, but Effective Go doesn't talk much about this. (It does say that library functions should avoid panic.)

Re: Why I’m not leaving Python for Go

#66

Earlier quoted context omitted.

It's actually worse than that. The blog has error handling code like: if err := datastore.Get(c, key, record); err != nil { return &appError{err, "Record not found", 404} } This is pretty typical Google Go error handling, where errors are only actually used as boolean flags. Errors are universally returned as type 'error' so to actually do anything with the error you have to first cast it to some specific type. But t…

> Errors are universally returned as type 'error' so to actually do anything with the error you have to first cast it to some specific type. But that type isn't part of the method signature so [...] This is quite correct and what's really broken with Go's approach to error handling and documentation.

I respectfully disagree. You almost never cast the error. Two approaches are common in the go community.

1. Error constants. These you can use == or a switch statement to do control flow with.

2. Custom Error Types. These you typically use a type switch which uses reflection to do dispatch off. In this case you might also then cast it if you need specific data off of the error but most of the time you don't need any more than the string the error() method returns.

Both of these cases use errors in the way go intends them to be used. For control flow at the location where it makes the most sense.

Re: Why I’m not leaving Python for Go

#67
post #20

The error handling style is certainly different - but it's not so bad. It's a matter of style and getting used to stuff. Maybe a better error handling mechanism is needed - but I'd prefer if it's not exception handling. Perhaps lisp style error handling? What ever that is - for I'm not familiar with it - but I keep hearing lispers brag about how awesome it is!

http://www.gigamonkeys.com/book/beyond-exception-handling-co... Think exceptions, but instead of blowing away the stack on the way up to your exception handler, it gives you the option of resuming execution in some way where you left off. It also lets you encapsulate error handling better.

I am glad to see some CL condition system pop up here. This article basically turned me off from Go and reading peoples support for C style error handling has made me question what the heck they are thinking.

There are actually several nice things about the CL system, but nothing there is going to convince someone that actually thinks not only that having every return value in your language serve the role of an error signal is reasonable, but actually arguing that it is equivalent from a programmers perspective or even a better method of programming.

Re: Why I’m not leaving Python for Go

#68
post #53

If you use a language that uses error codes, then you're forced to explicitly think about what to do in every single error case (or not, and accept the consequences). This can add a lot of mental overhead, but can result in a much more robust and well-thought-out program. But because more logic is involved period (to handle the robustness), the program is necessarily more complex. If you use exception handling, then…

I would guess that most (99%) of C programmers are lazy or has an rapid programming style then. Its a rare thing to see C source code that even do the simple thing like wrapping every write/read/print call with a loop that detects eintr. In my years of programming, I have yet to stumble on a other programer who even knows that one should be doing this. Looking at c libraries and their example code, almost every time,…

That's true but also C's error reporting differs greatly between libraries. Each library has a learning curve in how it wants it's errors checked. From the top of my head, 10 years after writing any C code there is check against NULL - guess the error, check against minus values - lookup minus values in a table, check against 0 - call method to get error string and many more.

Go standardises this in a super clean way. Every method that can error will return an error. If you try to write a method that calls methods that can error and you don't return an error then you will be extremely aware of that. After a few days of Go it will be physically painful to write code that eats errors.

So what Go did was to take the return parameter style of error reporting, mix in multiple return values to make that not suck and then optimize towards the local maxima of programming comfort within this paradigm.

The result - as anyone who has been writing go for a few months can tell you - is something that works incredibly well. I'd say it works better then exceptions style all but that may be my personal preference.

Re: Why I’m not leaving Python for Go

#69
I write Python and Go code every week, and have since I started using Go almost 2 years ago.

I appreciate Go because I'm working hard to become an engineer who builds robust software rather than a sloppy hacker that throws scripts together. One significant difference between the former and the latter is carefully handling errors versus not.

Python's error handling seems much more succinct only because most of us don't both handling errors at all! Every other line throws many exceptions, but we ignore this for convenience. (Those ugly "except ___:" statements ruin our oh-so-cool one-liners!)

Bottom line:

When I feel like having fun making something simple and getting it done _fast_, I use Python.

When I feel like building something that _needs_ to work -- especially anything that does more than one thing at a time, or should use all cores efficiently -- I use Go. And yes, that means taking error handling seriously.

Re: Why I’m not leaving Python for Go

#70

If you use a language that uses error codes, then you're forced to explicitly think about what to do in every single error case (or not, and accept the consequences). This can add a lot of mental overhead, but can result in a much more robust and well-thought-out program. But because more logic is involved period (to handle the robustness), the program is necessarily more complex. If you use exception handling, then…

The following illustrates how you use Go errors as if they were exceptions: func A() error { err := compute.Something() if err != nil { return err } return nil } Throwing errors up the return chain using error values is really very little different than throwing up the return chain using exceptions, except that now there is only one way to return, and it is always clearly marked. You return where you say "return". An…

How is that different from

    func A() error {
        return compute.Something()
    }
Post reply on HN