News for hackers. Stuff that matters.
Re:Declined Proposal: A built-in Go error check function, “try” by curtis on Tuesday July 16, 2019 @08:02PM (#20455123)
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.
Re:Declined Proposal: A built-in Go error check function, “try” by guessmyname on Tuesday July 16, 2019 @08:25PM (#20455259)
I 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.

Re:Declined Proposal: A built-in Go error check function, “try” by crimsonalucard on Tuesday July 16, 2019 @08:57PM (#20455462)
The 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.

Re:Declined Proposal: A built-in Go error check function, “try” by millstone on Tuesday July 16, 2019 @11:01PM (#20456038)
Why 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.

Re:Declined Proposal: A built-in Go error check function, “try” by crimsonalucard on Tuesday July 16, 2019 @11:51PM (#20456264)
Ok 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.

Re:Declined Proposal: A built-in Go error check function, “try” by mcintyre1994 on Wednesday July 17, 2019 @06:34AM (#20458042)
I'm interested in the zero runtime errors piece - how would a language with the maybe monad handle an out-of-memory error at runtime?
Re:Declined Proposal: A built-in Go error check function, “try” by crimsonalucard on Wednesday July 17, 2019 @12:46PM (#20461429)
There 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.

Re:Declined Proposal: A built-in Go error check function, “try” by sagichmal on Tuesday July 16, 2019 @08:27PM (#20455276)
Go 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.

Re:Declined Proposal: A built-in Go error check function, “try” by inlined on Tuesday July 16, 2019 @08:30PM (#20455306)
I 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.
Re:Declined Proposal: A built-in Go error check function, “try” by repolfx on Wednesday July 17, 2019 @06:19AM (#20457986)
Twice as long and half as long as what?

I often get the feeling that Go users are implicitly comparing it to languages like Python or JavaScript.

I've watched a client try to debug a Go codebase they had. It was sad. Their web server just returned 500 Internal Error and they tried to track down why from logs, but by the time the error had made it back up to the serving loop most information about where it came from had been lost. I suggested they attach a debugger to a server to see what's happening, they said debuggers don't work that great in Go and so people don't use them much.

If they'd been using exceptions they'd have a stack trace and could have pinpointed the source of the fault in seconds.

Re:Declined Proposal: A built-in Go error check function, “try” by meddlepal on Tuesday July 16, 2019 @10:16PM (#20455828)
Today I spent two hours tracking down why a nil pointer was occurring in my code. Turns out I forgot to pass it along to the struct initializer through one of the damn factory functions I need to create so I can hide internal fields properly... this was nested code in a framework.

Tell me again how easy it is to debug Go. In other languages the compiler can just tell me in _seconds_ that I done fucked up.

If you response includes "You're doing it wrong if you have deeply nested framework code" then you can rightly fuck right off too.

Re:Declined Proposal: A built-in Go error check function, “try” by sagichmal on Wednesday July 17, 2019 @12:09AM (#20456368)
Why are you using factory functions? Why are you trying to hide internal fields? The description of what you have to do is setting off some warning bells. It's certainly possible to write difficult-to-maintain code in any language.

> If you response includes "You're doing it wrong if you have deeply nested framework code" then you can rightly fuck right off too.

I mean, can you point me to an example? Absent more context, I'm pretty confident that you're indeed doing at least something wrong...

Re:Declined Proposal: A built-in Go error check function, “try” by meddlepal on Wednesday July 17, 2019 @01:16AM (#20456692)
Because we don't want to export internal fields of structures in our API or we need to perform initialization logic before considering the structure ready for use?

That's a pretty common use case but ignore that for a moment and just distill the problem down to it is possible to have null pointer issues in Go code.

Another example eith sufficient use of goroutines and channels it gets really tricky to debug something when a receiving channel blocks because something isn't sending.

There's plenty more. I don't find Go any simpler to debug than Java, Kotlin, Rust, or Python and in many cases it is significantly more difficult because you're constantly fighting the type system or working through huge amounts of boilerplate.

Re:Declined Proposal: A built-in Go error check function, “try” by sagichmal on Tuesday July 16, 2019 @08:33PM (#20455331)
That 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.
Re:Declined Proposal: A built-in Go error check function, “try” by millstone on Tuesday July 16, 2019 @11:19PM (#20456120)
Disagree hard!

    a = append(a[:i], a[i+1:]...)
That’s the recommended implementation of erase(). After this, is the original object referred to by ‘a’ modified? How can you tell?

Let’s pop from a stack:

    x, a = a[len(a)-1], a[:len(a)-1]

Did you read that 100x faster than ‘a.pop()’?

Now this:

    a = append(a[:i], append(make([]T, j), a[i:]...)...)
This is an operation called “expand.” What does it do? It is an honest question, I have no idea.

These are completely idiomatic examples taken from the Go wiki. They are not readable.

Re:Declined Proposal: A built-in Go error check function, “try” by AsyncAwait on Wednesday July 17, 2019 @12:47AM (#20456548)
The number of times I had to do this in practice over tens of thousands of lines of production Go code is about 3.
Re:Declined Proposal: A built-in Go error check function, “try” by badtuple on Wednesday July 17, 2019 @01:26AM (#20456729)
That surprises me. I have to manipulate slices all the time! Popping an item from a slice, reversing one, or clearing one without allocation in a hotspot is super common for me.

I've used Go professionally for 6 years and love it, so the patterns are ingrained in my head and don't bother me. But it seems pretty clear that it's much more arcane than alternatives.

Re:Declined Proposal: A built-in Go error check function, “try” by sagichmal on Wednesday July 17, 2019 @12:06AM (#20456355)
Slice operations are deliberately verbose in this way so as not to hide the cost of allocation that goes along with them. They are not common in code, but they do make good strawmen when you want to counter general points with specific ones.
Re:Declined Proposal: A built-in Go error check function, “try” by meddlepal on Wednesday July 17, 2019 @01:43AM (#20456817)
I don't think myself or any other Go devs I have worked with have once thought about allocation cost when using slice operations. This may be something super common for C/C++ devs but the big adopters of Go are Python and Java converts where we just don't pay attention to this stuff and after a decade or more of writing this kind of code were not going to suddenly start thinking in terms of memory allocation cost.

I think this is one of those mistakes in the language that exist because early-on Go could have been a true systems language but it's been adopted by a large number of devs more as an infra and high-level automation language where correctness is more important than performance.

Re:Declined Proposal: A built-in Go error check function, “try” by edflsafoiewq on Wednesday July 17, 2019 @02:10AM (#20456938)
Slice operations are verbose because abstracting over them requires generics. Generic operations which don't allocate, like pop, are just as verbose as generic operations which do, while operations on slices of a specific type can be made non-verbose because it is possible to abstract over those. There is no principle of "deliberate verbosity so as not to hide the cost of allocation".
Re:Declined Proposal: A built-in Go error check function, “try” by inlined on Wednesday July 17, 2019 @08:42AM (#20458786)
Aligned incentives? Making a “simple” operation as hard to write as it will be on the machine.
Re:Declined Proposal: A built-in Go error check function, “try” by wutbrodo on Wednesday July 17, 2019 @01:19PM (#20461824)
While not objectively a bad thing, that's at the crux of the problem many have with Go: it sets the bar very, very low for getting in your way instead of trusting you to be even slightly competent. Knowing basic data structures is engineering 101,and any engineer who'd (eg) blindly use std::find on a vector or "in" on a list in performance-critical code without understanding it isn't someone who should be committing code without review in any case. Inefficient data structure operations are also precisely the kind of thing that's easy to catch in code review.

Don't get me wrong, this isn't a general-purpose argument and I'm not one of those people who thinks that the language should completely get out of your way: eg I'm not a Rust user but its unergonomic handling of memory safety seems far preferable to the ease with which you can shoot yourself in the foot with C++. I definitely see the appeal of Go's handholding in a directional sense. But the degree to which it takes it makes it feel like an unserious or educational language, unnecessarily difficult to get actual work done in, like Javascript but for the exact opposite reasons (and to be clear, Javascript is INFINITELY worse).

This makes it sound like Im more negative on Go than I am, but I think it's the first time I've been able to articulate what deflated my initial interest in it and kept me away from it. Perhaps if feel differently if I had still been a student and new to programming when Golang was released.

Re:Declined Proposal: A built-in Go error check function, “try” by fredmorcos on Thursday July 18, 2019 @10:45AM (#20470333)
> While not objectively a bad thing, that's at the crux of the problem many have with Go: it sets the bar very, very low for getting in your way instead of trusting you to be even slightly competent.

And there's nothing wrong with that, that's exactly Go's target audience.

Re:Declined Proposal: A built-in Go error check function, “try” by baby on Tuesday July 16, 2019 @08:45PM (#20455394)
I 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.

Re:Declined Proposal: A built-in Go error check function, “try” by abtinf on Tuesday July 16, 2019 @09:45PM (#20455688)
Go is the only language where I look at the standard library source instead of google whenever I run into an ambiguity in the docs. I think there are three reasons for this.

First, the docs link to the actual line in source, so it’s just a click away and available in the exact context I need it.

Second, I know I’ll be able to understand it: there are usually very few dependencies, so I can usually get all the context I need from a single file; the source formatting is familiar; code style, like variable names, are familiar because of the cultural influence of the Tour of Go; and there is usually no magic anywhere—I know that things are exactly what they appear to be, like when I see a variable declaration, it is not secretly calling a complex function (this is vital to human knowledge and is aligned with Objectivist epistemology’s “law if identity”).

Third, every time I look at the standard library source, I become a better programmer. I’ve lost track of the number of times I’ve thought to myself “oh, that’s a clean way to organize this kind of code!” I often end up immediately using what I learn from the stand library source.

Re:Declined Proposal: A built-in Go error check function, “try” by bmurphy1976 on Tuesday July 16, 2019 @10:15PM (#20455826)
I agree, and if others disagree they should comment and explain why instead of downvoting you.

One of Go's major selling points (for me anyway) was a solid standard library written mostly in conventional Go style. It's a great example of how Go code should be written, and a wonderful learning tool for the language.

It also makes participating in the community easier because that's one less thing you have to learn in order to contribute.

Re:Declined Proposal: A built-in Go error check function, “try” by nkozyra on Tuesday July 16, 2019 @08:54PM (#20455446)
> 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

Re:Declined Proposal: A built-in Go error check function, “try” by erik_seaberg on Wednesday July 17, 2019 @12:08AM (#20456360)
Experts' code should be clearer and more concise than novices' code. If that's not true, there's no payoff for getting more proficient with the language, and it's not doing enough to help you.
Re:Declined Proposal: A built-in Go error check function, “try” by oftenwrong on Wednesday July 17, 2019 @06:50AM (#20458120)
golang is not primarily designed for experts

"The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt." – Rob Pike

Re:Declined Proposal: A built-in Go error check function, “try” by pjmlp on Thursday July 18, 2019 @05:07AM (#20468050)
Ironic in a company that prouds itself of PhD hiring games.
Re:Declined Proposal: A built-in Go error check function, “try” by nkozyra on Wednesday July 17, 2019 @12:15AM (#20456401)
This is about readability. There are many other attributes of code (idiomatic? design? efficiency?) that differentiate. But I should be able to grok anyone's code within reason.
Re:Declined Proposal: A built-in Go error check function, “try” by thatswrong0 on Tuesday July 16, 2019 @09:25PM (#20455584)
I wish gofmt would let you set a desired line length and break it for you.. prettier has me spoiled in that regard
Re:Declined Proposal: A built-in Go error check function, “try” by mcbits on Tuesday July 16, 2019 @09:39PM (#20455655)
If a tool is going to enforce line length limits, I'd rather have it spit a warning/error than silently try to guess a good place to break the line automatically. Otherwise, an editor tool that soft-wraps long lines at the (often poorly) guessed location without touching the code would be better.
Re:Declined Proposal: A built-in Go error check function, “try” by thatswrong0 on Wednesday July 17, 2019 @12:52AM (#20456567)
But that’s the thing about prettier - it wraps exceptionally well because it actually parses the AST. I never think about how I space my JavaScript anymore because it always does it correctly.. it’s one less thing to get in my way when I code
Re:Declined Proposal: A built-in Go error check function, “try” by mcbits on Wednesday July 17, 2019 @03:18AM (#20457242)
The number of options that prettier exposes (despite boasting about being "opinionated", i.e. disregarding the user's opinions) suggests that there are people with different aesthetics or accessibility needs who would not consider one style to be always correct.

IMHO we're about 10 years overdue for committing a canonical representation of that AST to version control instead of treating a particular serialized visualization of it as the single source of truth (and spending countless hours debating which format is "good enough" for everyone in every situation).

Re:Declined Proposal: A built-in Go error check function, “try” by hacknat on Tuesday July 16, 2019 @10:59PM (#20456031)
You can always set your defaults for your editor.
Re:Declined Proposal: A built-in Go error check function, “try” by justinclift on Tuesday July 16, 2019 @09:15PM (#20455541)
Packages extensively using reflect + interfaces together can be a bit of a pain to work through. :/
Re:Declined Proposal: A built-in Go error check function, “try” by sagichmal on Tuesday July 16, 2019 @09:58PM (#20455754)
Absolutely. But those are clear code smells. Any org with competent code review would flag them and kill them before they proliferated.
Re:Declined Proposal: A built-in Go error check function, “try” by jeremyjh on Tuesday July 16, 2019 @11:20PM (#20456125)
Would you consider k8s to be developed by a competent org? They have 2324 func declarations that take or return an interface{} on master right now.
Re:Declined Proposal: A built-in Go error check function, “try” by sagichmal on Wednesday July 17, 2019 @12:07AM (#20456357)
Kubernetes, like Docker, is notoriously bad Go. The authors essentially transliterated Java.
Re:Declined Proposal: A built-in Go error check function, “try” by inlined on Thursday July 18, 2019 @12:11AM (#20466619)
This. It was really hard to enforce supplementary style across my team to match common conservatism in popular codebases (e.g. only return a single value or a value and bool/error. Don’t expose channels in APIs) when K8s so blatantly fails them.
Re:Declined Proposal: A built-in Go error check function, “try” by justinclift on Wednesday July 17, 2019 @09:26PM (#20465798)
Have you seen the internals of the Go http library? :)
Re:Declined Proposal: A built-in Go error check function, “try” by inlined on Thursday July 18, 2019 @12:08AM (#20466602)
Have you seen the internals of the rand library? HTTP uses interfaces cleverly to detect optional interfaces. Today I found out that rand.Rand does a type check on every core method to see if it’s source is the hidden type for global methods.
Re:Declined Proposal: A built-in Go error check function, “try” by unixsheikh on Tuesday July 16, 2019 @08:45PM (#20455395)
Exactly.
Re:Declined Proposal: A built-in Go error check function, “try” by pixelrevision on Tuesday July 16, 2019 @08:49PM (#20455417)
I 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.
Re:Declined Proposal: A built-in Go error check function, “try” by mvndaai on Friday July 19, 2019 @02:00AM (#20476487)
The 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