I've written a lot of Go, I started four years ago when my workplace at the time wanted to ditch writing web services in Ruby. We were very deep into containers, so the obvious choice to the team lead was to do what the Docker folks were doing.
My take is that Go is a great language when you're working with incompetent people. It's so limiting in the abstractions you can build with it, that it is very difficult to write code that is not immediately obvious in its purpose. Go is easy to teach, easy to review, and it's so syntactically deficient and the tooling is good enough that it's hard to bikeshed. This ultimately improves the experience of writing code at work, and its static type system makes it easier to reason about large code bases for the folks who are used to using Ruby and Python at scale.
But Go is also awful in so many ways, its such an obvious step backwards in its design and the community is so dogmatic about Go and the Go authors.
On large code bases you almost invariably end up working around the deficiencies with the empty interface, code gen tools that add non standard syntax, and lots, and lots of copying code and code patterns over and over again. Any common pattern you see emerge, that you'd like to create a generic structure for, is probably impossible to encode without type variables. Go also notoriously pushes many errors that would have been caught at compile team to runtime because of its weak type system. With Sum types, it's difficult to make improper states illegal, and default values lead to subtle bugs because they essentially behave as predictable garbage.
Go honestly keeps me from having faith in software engineering as a craft. It's the acceptable of the status quo, or worse, moving backwards in order to fit the needs of the lowest common denominator.
"My take is that Go is a great language when you're working with incompetent people. It's so limiting in the abstractions you can build with it, that it is very difficult to write code that is not immediately obvious in its purpose."
Do you think this is intentional? Similar to how java is incredibly restrictive, and thus great for corporate programming environments?
“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.”
Yet Turbo Pascal for MS-DOS, with more features than Go has currently, did already have faster compile times on those clunky 8086 CPUs, let alone on modern 21st century hardware.
Fast compilation times in Go are only a surprise for a generation that never used native programming languages with native support for modules.
As for C++ compilation times, yes they are an abomination when doing make world from scratch, including third party dependencies, with heavy template code.
However modules are around the corner and they were just voted into C++20.
I feel that there is a certain irony that while Java shared some of Go's goals in terms of target audience, is currently much more advanced than Go is, or might ever be even if all Go 2.0 goals get fully implemented.
I have come to see it as a tool for the folks that want a plain better C and are happy with having a GC around to keep them productive.
This is why I do not think adding generics is a good idea. Go excels at the areas I described. There's obviously a need for a language that is limiting, and many people enjoy Go for that reason.
> Which specific "code gen tools" and "non standard syntax"?
I've done codegen through a DSL and through comments. The DSL is actually typed, which is nice, but it's also its own mini-language that you have to teach people on top of the Go basics. It's also a general rule that it should be used sparingly because it tends to generate very verbose and ugly code.
> What kinds of errors would you expect to be "caught at compile time" with a different type system?
The empty interface, which must be cast to the contained type to be useful, is an obvious one. Generally type casts, error handling, pointer dereferences, all can lead to run time bugs.
At the macro level, a language with a rich type system should make invalid program states fail to compile. With true phantom types, for example, one can make a state machine that will fail to compile if a state transition invariant is not satisfied.
> What kinds of "default values lead to subtle bugs"?
The issue is that the notion of a "default value" makes little sense. For many applications 0 is not a good choice for the initial value of every integer. Someone who forgets to set the integer to an appropriate value will run into the same error as in C, except instead of a trash value, they will find a consistently bad value, which is slightly better.
Better to throw an error if an uninitialized value is used, and demand that all struct fields be set unless the struct author has explicitly set default values.
> Have you looked into...
Yes, I have seen the proposals. I am an opponent to generics in Go. I think Go excels at exactly that which I described in my first post. If you add more to the language, I believe it will morph into a poor mans Java instead of a better Go. Better to simply move to a language that was built from the ground up with the intention of providing abstractions (I like Rust), and use Go when its upsides outweighs its downsides. Many times, they do, especially in businesses where the talent pool is limited.
My take is that Go is a great language when you're working with incompetent people. It's so limiting in the abstractions you can build with it, that it is very difficult to write code that is not immediately obvious in its purpose. Go is easy to teach, easy to review, and it's so syntactically deficient and the tooling is good enough that it's hard to bikeshed. This ultimately improves the experience of writing code at work, and its static type system makes it easier to reason about large code bases for the folks who are used to using Ruby and Python at scale.
But Go is also awful in so many ways, its such an obvious step backwards in its design and the community is so dogmatic about Go and the Go authors.
On large code bases you almost invariably end up working around the deficiencies with the empty interface, code gen tools that add non standard syntax, and lots, and lots of copying code and code patterns over and over again. Any common pattern you see emerge, that you'd like to create a generic structure for, is probably impossible to encode without type variables. Go also notoriously pushes many errors that would have been caught at compile team to runtime because of its weak type system. With Sum types, it's difficult to make improper states illegal, and default values lead to subtle bugs because they essentially behave as predictable garbage.
Go honestly keeps me from having faith in software engineering as a craft. It's the acceptable of the status quo, or worse, moving backwards in order to fit the needs of the lowest common denominator.