5 ms·
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 c
by d0m 14y ago
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:
def whatever(request):
my_int = int(request.POST['some-param'])
Note that, in that case, we don't check if 'some-param' is in POST. Neither what happens if it's not a number.. Basically, an exception will be raised and a 404 will be shown.
- 0xABADC0DA 14y agoIt'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 that type isn't part of the method signature so you have to dig around in the source or, if you are very lucky, it was documented someplace. You end up having actual error handling plus even more error handling for if you got the error type wrong. For instance if datastore could return 'record not found' or 'io error' then they would usually be treated the same way by the code because to do otherwise would be even that more of a hassle.
- eternalban 14y ago> 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.
- zaphar 14y agoI 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.
- eternalban 14y agoI respectfully disagree: http://golang.org/src/pkg/net/timeout_test.go#L39 http://golang.org/src/pkg/net/timeout_test.go#L39 edit: You should note that the above test code is actually far less verbose than the analogous end-user code, given that the timeout_test.go clearly expects the 'err' var to be a net.Error. Now consider the case of a network subsystem, with funcs having in args of type 'bufio.Reader' and/or 'bufio.Writer'. At some prior point you may have set 'net.Conn.SetReadDeadline(aPointInTime)', and in your stream processing funcs you may naturally encounter either net.Error (due to timeout) or buffer overruns, etc. What would call site look like? Can you safely cast to (net.Error) like the test code? Not unless you can live with panics on interface type mismatch. // hmm. what is the error type? _, e := readMessage(reader) switch errType(e) { // you write this reflective func case NET_ERROR: if e.(net.Error).timeout() { /* handle timeout */} default: /* deal with other errors */ }
- agentS 14y agoNot sure what buffer overruns you are referring to, or why this case requires reflection at all. err := readMessage(reader) if n, ok := err.(net.Error); ok && n.Timeout() { // handle timeout } else if err != nil { // handle other errors } You can see an example of exactly this pattern here: http://golang.org/src/pkg/net/http/server.go?s=29962:30008#L1000 http://golang.org/src/pkg/net/http/server.go?s=29962:30008#L...
- 14y ago
- agentS 14y agoI guess you are super lucky: https://developers.google.com/appengine/docs/go/datastore/reference#variables https://developers.google.com/appengine/docs/go/datastore/re... or even https://developers.google.com/appengine/docs/go/datastore/reference#Get https://developers.google.com/appengine/docs/go/datastore/re... 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.
- 0xABADC0DA 14y agoI think this is exactly the point. You have to read the comment to get the error types (isn't compiler accessible), it doesn't list what all the possible error types are (doesn't say the ones documented are exhaustive), and the code returns a singleton error (no state) presumably so the caller doesn't have to do a bunch of casts..
- agentS 14y ago> You have to read the comment to get the error types (isn't compiler accessible), it doesn't list what all the possible error types are (doesn't say the ones documented are exhaustive) You're absolutely right. People should be able to use libraries without reading their documentation, and instead rely on compile failures to slowly iterate their code towards perfection. /s Seriously, though, I believe expecting programmers to read documentation of a library they're using is a pretty low bar. Also, no it doesn't list what all the possible error types are. To do this would require what amounts to checked exceptions in Java. The issues with these are relatively well known. First, it complicates versioning as adding a new error type is a breaking change for all clients. When they get an error from an API, most clients either return that error verbatim, decorate that error slightly and return the decorated error, or handle a few specific error situations and return an error in all other cases. Declaring all possible error types makes your programs brittle, as it is easy for libraries you are using to break your code. Second, they are a hassle for larger programs that touch many systems. It is easy to declare that you return an EntityNotFound error. But it is not so easy to declare that you return an EntityNotFound, MemcacheCASConflict, FileNotFound, FileExists, PermissionDenied, Timeout, InvalidJSON, ConnectionClosed, or TemplateRenderingFailed error. This is perfectly reasonable set of errors for a simple method that gets a value from datastore (possible caching it) decoding a field as json, and writing a template to an HTTP connection. Any 'simple' wrapper of this method then inherits all of these declarations. Now certainly with Java, IDEs will "fill in all the forms" for you, so this problem is a little more palatable, but Go does not require programmers to use (often heavyweight) tools to make them productive. > code returns a singleton error (no state) presumably so the caller doesn't have to do a bunch of casts This is a little disingenuous, as you don't really know why they made it a singleton error. I can't think of any state that would be useful in this situation, can you? The Java version of this API throws an exception with a single field, the Key that could not be found. I think this is supremely unhelpful and just adds clutter to the documentation, as the user of this method clearly already has this information in hand.
- anacrolix 14y agoYeah this needing to dig through the source is no end of pain, when you do actually want to handle the error.
- hasenj 14y agoYou can switch on the error type, since "error" is an interface. switch err.(type) { case Type1: // do something case Type2: // something different default: // something else }
- agentS 14y ago> Basically, an exception will be raised and a 404 will be shown. 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 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.