4 ms·
1 is a subset of a smaller issue. Default params are just a way to declare variadic functions more easily, but the language doesn't allow variadic functions at
by vec 9y ago
1 is a subset of a smaller issue. Default params are just a way to declare variadic functions more easily, but the language doesn't allow variadic functions at all. In go trying to define `add(int x, int y)` and `add(float64 x, float64 y)` is a compile error, even though the compiler can tell full well which one I want to use where.
2 is so annoying. Half the sdtlib wants you to use `foo.NewStruct()` and the other half uses `&bar.Struct{}`. As far as I can tell the rule is to use a bare definition where possible and only declare a New function if the zero value isn't meaningful. But there's no way for a library author to force the use of new and/or disable bare struct literals, and there's no way for an API consumer to know which category a given library will fall into other than by rote memorization. It's practically designed to invite user error.
Both of these seem emblematic of a bigger problem in the design philosophy of go. It's optimized for simplicity, but often at the expense of making idiot proof interfaces difficult or impossible to build. This seems like a fundamental misunderstanding of what makes programming difficult in the first place. My package's users (including future me) aren't going to know or care about how the internals of whatever I'm throwing together work, they just want to use the API to solve their problem with as little extra contextual knowledge as possible. Go doesn't let me write an interface where they don't have to know or care, all in service of a definition of "simplicity" that doesn't seem to actually make anything easier.
- masklinn 9y ago> 1 is a subset of a smaller issue. Default params are just a way to declare variadic functions more easily, but the language doesn't allow variadic functions at all. In go trying to define `add(int x, int y)` and `add(float64 x, float64 y)` is a compile error, even though the compiler can tell full well which one I want to use where. That's function overloading rather than variadic functions. Variadic would be `add(xs int..)` where you can pass in any number of int, and they'll be collected into a slice or whatever.
- randomdata 9y ago> It's optimized for simplicity, but often at the expense of making idiot proof interfaces difficult or impossible to build. But technically speaking it is optimized for simplicity of reading code. The idea, whether it has worked out in practice or not, was that Google could take people with limited developer experience and put them into a Go codebase and have them be able to follow along with the project with minimal introduction and explanation from already busy teammates. Your function overloading (Go does support veridic functions!) example is a good example of where the author and compiler know full-well what the intent is, but people coming in five years later may not be entire clear on what you are trying to say. `add` is a simplistic example, but it is easy to see, and I am sure many of us have experienced, how this can be a problem in more complicated cases. As you have pointed out, optimizing for the simplicity of reading has resulted in increased complexity of implementation. You've only just scratch the surface of the gotchas in Go. However, that's the tradeoff. Engineering is all about managing tradeoffs and some will value readability (assuming the theory that Google has holds – I don't know that anyone has formally measured this) and others will value writability. Everyone has different goals and is developing in different environments. There is never going to be a solution that fits everyone. If there were, we wouldn't need software engineers anymore.
- vec 9y agoI actually find go extremely difficult to read. The abstractions tend to be both shallow and leaky, the syntax is noisy, and the very limited feature set forces a particular coding style whether it's appropriate for the problem at hand or not. It limits expressiveness, which I find makes it harder for an author to communicate intent. In other words, go makes it extremely clear how a piece of code works at the expense of knowing what a piece of code is trying to accomplish and why I might want to invoke it. I generally think that's a poor tradeoff.
- randomdata 9y agoGiven Google's penchant for being data-driven, it would be interesting to see if their assumptions actually play out in the real-world or not. Everyone has an opinion about programming languages, but rarely does anyone want to look at it scientifically. That said, perhaps they have and don't want to admit that Go falls short. But they've been open about being wrong before when applying the scientific method and getting unexpected results.
- z0r 9y agoit isn't particularly easy to chase logic through lasagna layers of interfaces and structs. it isn't even easy to read bog standard code made out of for loops glued together (because that's all you have to work with) every time i look at another tedious manually written set operation that would been have a simple expression in another language (python is an excellent example) i am deeply pained. every time failure of abstraction forces you to re-implement such things there are opportunities for bugs to creep in. go is designed to be easy to write, and (in my experience so far) the natural consequence is that any project made up of modules spanning more than one or two directories quickly becomes very, very hard to read. a common exception to that is when code has to do many set-like operations, which can become very hard to read without having to sprawl out beyond even a single file. very common when dealing with multi-parameter/multi-result RPCs