6 ms·
A lot of Go programmers didn't like this proposal at all. I'd like to think this is just because they didn't think it was good enough. However, it seems that
by curtis 7y ago
A lot of Go programmers didn't like this proposal at all. I'd like to think this is just because they didn't think it was good enough. However, it seems that many, many Go programmers didn't like it because they think Go error handling is just fine the way it is.
- guessmyname 7y agoI am one of the Go programmers who didn’t like this proposal. I also spent a significant amount of time discussing with many people, including the Go team, and I am glad the proposal was declined, not because I like “if err != nil {…}” but because the proposal to add “try()” was not solving a good problem. Many, and I would say, every Go programmer wants better error handling, but “try()” was not it. I hope the Go team keeps exploring other ideas to hopefully one day have a better error handler.
- crimsonalucard 7y agoThe maybe monad is the best solution for this. Usually to support this the language needs Enum support and a proper type system neither of which golang has. So I'm ok with the developers just baking in syntax for an error monad with specific sugar for extracting the value or handling an error.
- millstone 7y agoWhy is a monad the “best” solution? Best according to what criteria? Special purpose syntax can buy you a lot more. For example Swift’s try makes it obvious which statements contain error handling without burdening each expression.
- crimsonalucard 7y agoOk let me tell you the criteria. There are two. First: The monad allows for composition of functions. Returning two values does not. It breaks the flow of a function pipeline and forces you to handle every error in the same way. Second: Extracting the value via pattern matching guarantees that the error will either be handled or used correctly. This is a way to 100% guarantee that there are No runtime errors. That's right. Using the error monad with pattern matching makes it so that there is zero room for runtime errors. Why create a language that has runtime errors? Create a language that forces you to handle all possible runtime errors before it even compiles. According the criteria of safety, zero runtime errors, and expressivity via composition the monad is the Best solution. There is literally no other way of error handling that I know of that can catch runtime errors at compile time. I know you tried to flip my statement on it's head by using the term "criteria" as if there are many many different criteria for "best." And you are right, programming is an opinionated thing. However, ZERO runtime errors is a too powerful of a feature to assign to a specific criteria. Such a feature is so powerful, it should be part of EVERY criteria. If you don't understand completely what I mean by "composition" or how pattern matching and a maybe monad can guarantee a runtime error will NEVER occur, ask me to elucidate, I'm happy to clarify.
- mcintyre1994 7y agoI'm interested in the zero runtime errors piece - how would a language with the maybe monad handle an out-of-memory error at runtime?
- crimsonalucard 7y agoThere is a way of which (to my knowledge) is not implemented in any technology. Presuming you know how the maybe monad (or similar named monads) handles errors. A MaybeOutOfMemoryError works in a similar way in the sense that any attempt to use the value meaningfully will force you to handle the error. data MaybeOutOfMemoryError a = OutOfMemoryError | Some a ioFunction :: MaybeOutOfMemoryError a -> IO ioFunction OutOfMemoryError = println "ERROR" ioFunction Some _ = println "No ERROR" exhaustive pattern matching with the error flag enabled makes it so that if you forget the OutOfMemoryError case an error will occur during compile time. Any function that can potentially trigger a memory error should be forced to be typed like this. However in programming, ALL functions can potentially do this, and side effects outside of the scope of the function (total memory available) will trigger it meaning that the only way to do this effectively is to make ALL functions typed this way. Which is inconvenient to say the least. That being said you can just type the main function as something that can only accept this monadic value forcing users to wrap this handling in a top level function: myWrittenProgram :: MaybeOutOfMemoryError a -- not defined in this example -- main is forced to be typed this way just like how in haskell it is forced to be typed IO () main :: MaybeOutOfMemoryError a -> IO () main Some a = printLn a main OutOfMemoryError = printLn "Error out of memory" Obviously the above has some issues with the rest of haskell syntax and the way things are done, but I'm just showing you a way where it is possible to make sure that a memory runtime error does not happen (that is an unhandled runtime error). That being said unless you know haskell or know what a maybe monad is, you wouldn't be able to fully comprehend what I said. Exception monads exist in haskell, but nothing is forcing the main function to be typed this way.
- sagichmal 7y agoGo error handing _is_ fundamentally fine the way it is. That is, the verbosity would certainly benefit from some sugar, but the semantics -- errors managed by separate expressions/blocks immediately adjacent to the error-generating code -- is fundamental to the language, and one of its great strengths.
- inlined 7y agoI repeatedly tell people that Go takes twice as long to write and half as long to debug. Unless you write perfect code on the first try, the trade off is probably worth it.
- sagichmal 7y agoThat feels about right, but missing the most important measure, IMO, which is it takes 10-100x less time to read and understand a new codebase.
- baby 7y agoI spent years as a consultant reading codebases in different languages. I can tell you that Golang win hands down for clarity of code and structure of projects (and perhaps second after Rust in terms of security. If only it had options<>...) So yeah, it's actually quite fast to dig in a Golang codebase. You notice that as a normal user when you find it faster to read the standard library vs reading the doc, or when you read an implementation instead of reading a spec/algorithm to learn about it. My guess is that gofmt is a huge factor in this, but also the fact that there's not a huge amount of built ins, anf that the standard library is pretty complete.
- nkozyra 7y ago> My guess is that gofmt is a huge factor in this It really is. My code looks like your code and the next person's code. Go is opinionated and strict and that makes reading other people's code so much easier
- pixelrevision 7y agoI don't really care about try/catch, I'd just rather they come up with a standard for wrapping errors so there is more visibility as they get bubbled up. Currently you can write code to do this but most packages will not be doing the same. There also will always be some member of your team fighting you about "simplicity" when you talk about wanting to have more info than a string to log.
- mvndaai 7y agoThe go 1.13 version of errors will have the `Is`, `As`, and `Unwrap` which make this almost a standard in go. They expect you to be able to unwrap but have not created a normal way to wrap. https://tip.golang.org/pkg/errors https://tip.golang.org/pkg/errors