Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I could not agree more with this. Go is so frustrating to me because there is so much I like but these things you listed make it miserable for me to use.

A basic option and result type could fix a lot of the issues around errors and null pointers. I know languages like Scala, Haskell, and Rust have type systems that are often considered too complex but Go doesn't need all that to add these two.



"Defaults are useful" was IMHO the biggest mistake Go made. I understand that it made the language a lot simpler but this was a simplification that ended up moving the complexity to the user, rather than just removing it.

I have seen so many bugs caused by default values, production outages. Plus the code is harder to understand because you need to consider the default value case, and make sure that it is only left at the default when intended, not by accident. (And the linter probably can't warn you because it isn't wrong to have the default value live in one path through the code).

One of my favourite things in more strongly typed languages is just adding a field to a struct then having the compiler point out everywhere that I need to make changes. The strictness both prevents bugs and saves time. Plus the code doesn't need to worry about invalid structures, you can often write code such that they literally can't exist.


Not to mention, some things just don't have a sensible or sane default. Needing the zero value to be meaningful has had so many negative downstream effects (nil being one of them) it's crazy people still defend this decision.


Not sure. If you declare a variable as of type string i think it really good that it is empty string as default. The other option is to be null.


I don't think it is. We had a production outage because someone was putting things into a map with the wrong key. Tests passed because they read (using a right key) and checked that they got a valid value. In this case an empty string was "valid". (Basically it deserialized correctly.) Sure the tests could have been better but this also wasn't the only bug due to default values. Imagine if 1% of the time the result of addition was randomly 5, it would cause havoc. Default values are the same. Sure, often they are a reasonable value, but when values that the coder didn't expect enter the system you are going to have a bad time. If the map reads failed tests would have failed, but also the crashing service would have been reverted and the problem found before it caused any real trouble. Not silently corrupting out data for a week.

The other option isn't null, the other option is an error. Ideally the code fails to compile. 99% of the time I would rather have an error than have my code silently be wrong. Failure is almost always better than corruption. (Don't get me started on Go's fmt lib that barfs crap into the output if you have your format string wrong, at least that is easy to lint for most of the time) And build failures are almost always the best because then the wrong code can't even make it to production.


A huge downside of that it that adding a new (public) struct field will be an incompatible change. And what people will do is add a non-public struct field with a setter method, both to avoid the compatibility break but also because for many of these fields the defaults are just fine (even though sometimes they're not) and no one lines having tons of boring boilerplate.


Having used Ocaml for quite some time, i can understand this. However, i cant tell people (junior devs, or devs who just want to work and does not care about comp-soyery) to learn an ML (+ all the FP idioms) with a straight face.

Having a (val, err) tuple IS more easy than returning a monad.

Sometimes (most times?) pure procedural code is just the best, and i really hate languages that have feature X but does not support it fully.

As an example i would not be happy with an monadic return type if the language did not have the option to use some sort of bind/return combo, and have full pattern matching support.

Thats why i champion Go for larger teams. Almost anyone can join the team in dive in without much previous Go knowledge. This is a rare feature and i dont know many other languages that has this property.


You really don't need to think about monads or functional programming to have option and result. The focus on explaining these in the context of sum types and monads only serves to distract most people. A list is a monad and people use them every day and they are fine.

> Having a (val, err) tuple IS more easy than returning a monad.

Arguments about which concept is easier for people to understand pretty quickly descend into subjectivity but I don't believe this is universally true. Why am I getting a value when there's an error? What do I return as my value when returning errors? Explaining to someone that a function returns (val, err) and only one of these values will be significant is more or less the same as describing a result.

Option is even simpler. It's a list that can have at most one item. Or, you know how in python you can set a variable to None? Here's how to do it in a strongly typed language.


I like Go for its standard library but truly hate its nil behaviour and default value semantics. Uber effectively built a static analysis tool from scratch to catch nil issues: https://www.uber.com/en-IN/blog/nilaway-practical-nil-panic-...


Indeed. I enjoy working in Go and have written various things in it over the last 8 years. Last year I toyed with Rust (very different learning curve!) and still prefer Go for its simplicity and development speed. But, I would love to have Rust-style enums in Go. The 'similarly named constants pretending to be enums' and 'returning nil if not found' patterns suddenly started feeling wrong.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: