Why I’m not leaving Python for Go
41–50 of 245 posts
Re: Why I’m not leaving Python for Go
#42Earlier quoted context omitted.
Your statement seems self-contradictory. Should we strive to learn new things, or should we not jump on the next bandwagon? Are you saying that we should try new things but not really try them very hard, or what? There is such a thing as progress, and in my opinion the way you get it is by spending lots of time trying new things and seeing which ones work. So I'm in favor of "leaving a language that was working well…
Because hype != progress. Hype is basically a bag full of air. You can try new things, but abandon the other ones because of hype (or thinking it's better cuz "ppl who don't know anything about languages said so") instead of true technical merit is pretty fucked up :) Now then again Go ain't bad, but I don't see it being better enough than Python to switch in this case. Python in better for many things as well. Not a…
Re: Why I’m not leaving Python for Go
#43If 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…
Re: Why I’m not leaving Python for Go
#44I 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 using "panic", you enable more concise and compositional code. By using error-returns, you are being more explicit and making it easier for the caller to handle errors at the call-site.Usually, functions that can fail are not the kind you desperately want to use in expressions anyway. So error-returns are more common. But there are many situations where errors can happen and where composition is a big win. In those cases, you reach for "panic".
If you look at some of the built-ins that can panic--I'm thinking of array-indexing and division and regexp.MustCompile(), for example--you notice that these would become very cumbersome if they used error-returns instead.
There's also the issue of initialization. That's the justification given in the case of regexp.MustCompile(). An initializer must be a single expression.
The words "panic" and "error" probably lead people to think that you should make the decision based on severity but I don't think that's right.
(That's just my take on it. I'm no Go expert so there are likely better ways to think about it.)
Re: Why I’m not leaving Python for Go
#45If 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…
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". And you return what you said you would.Re: Why I’m not leaving Python for Go
#46It's not "tempting to ignore errors". You're the programmer, if you want to ignore it, do so. I don't know why you'd want to ignore the returned value and possible error on a GET request - given that 1) it can fail for so many reasons, and 2) the suggestion that you might be "GETTING" something. Ignoring the error of a print statement is more acceptable since it's unlikely to occur and there's rarely a lot you can do…
That's his whole point. He doesn't want to ignore errors but feels like Go is so verbose about it that it's a pain for programmers to deal with it. Example in case, print . Would you check its return value every time you call it? No. Contrast that to other languages, such as python, where you don't ignore the errors because you know that if something goes wrong, an exception will be raised. It lets you do stuff like:…
I understand your point in general, but have to disagree with the example you chose. A 404 implies Page Not Found.
The Python framework I use (http://bottlepy.org/docs/0.9/_modules/bottle.html) makes this a 500 Internal Server Error, with the text "Critical error while processing request: /foo-bar". IMO, this is ugly, and not super user-friendly, so I usually end up writing try catches around "one-liners" to log a better error than a stack dump, and present a friendlier message.
If he really wants this kind of framework-provided error message, then a panic would be more appropriate, because the HTTP server in Go will do the same thing as bottle. It's definitely not going to be as succinct, but it'll be more succinct.
Re: Why I’m not leaving Python for Go
#47If 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…
If you want to handle some error in a way other than crashing, handle it. Web frameworks usually catch exceptions that arise while a request is being handled, finish the request, and keep handling new requests. You handle things more specifically only as needed.
I like that behavior so much more than having a program keep running in an unknown state unless you handle errors line by line (and value it more than keeping code execution where I can see it). I don't think my programming language knows what errors are very important, either — that depends way too much on context.
Re: Why I’m not leaving Python for Go
#48I do not have the same rule for python.
Re: Why I’m not leaving Python for Go
#49If 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…
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 line that can have an exception with it's own try/catch block, then yes, that is pretty much the same as handling explicit error codes. Which is why I consider that poor style in languages that have exceptions.
Separating error handling code apart from the logic flow of normal operation is simply not possible with error codes as function return values.
Re: Why I’m not leaving Python for Go
#50Earlier quoted context omitted.
That's his whole point. He doesn't want to ignore errors but feels like Go is so verbose about it that it's a pain for programmers to deal with it. Example in case, print . Would you check its return value every time you call it? No. Contrast that to other languages, such as python, where you don't ignore the errors because you know that if something goes wrong, an exception will be raised. It lets you do stuff like:…
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…
err := datastore.Get(c, key, record)
if err == ErrNoSuchEntity {
// entity not found
return
} else if err != nil {
// some other error
return
}
Don't really see the hassle you are referring to.