Ooof. I've just spent about 3 days debugging Go code that was copypasted x N, with minor (incorrect) modifications. Rewriting it with generics would have been about 30-min job and made it much more maintainable in the future.
Ooof. I've just spent about 3 days debugging Go code that was copypasted x N, with minor (incorrect) modifications. Rewriting it with generics would have been about 30-min job and made it much more maintainable in the future.
The tradeoff in Go seems to work reasonably well for services that doesn't want, or need, to handle complex application domain as fluently as concurrency. Essentially it works well for network/systems level code, and anything that looks like that.
But for code that is more of an encoding on an application/service domain, the lack if generics hinders reasoning more than it helps. There you have no use for the fancy concurrency stuff, it has to be abstracted away for the domain experts to be able to be productive. There are, usually, also enough code that global readability become less helpful, and unambiguous contracts/types across systems becomes moreso.
The latter case is massively helped by any way to enforce contracts over methods and types, as long as refactoring tools can reason over it. Nevertheless I do believe that locally (in methods/functions) a well behaved type inference and IDE tooling is better than extremely verbose type statements that I then make the IDE hide from me!
To me these are clearly different scenarios, but apparently not to most people, or these discussions would rarely occur, but we would have discussions about the characteristics of languages making them suitable for any specific task.
After all, for every solution there exists a possible language where the solution for a particular problem is part of the language, trivially making it the best language for that problem.
Also trivially, there exists a best language for me, personally, to solve any problem. This is the hypothetical language which encodes and compensates for my individual perceptual and cognitive bias.
Now, in a large enough enterprise, the most important contracts, and hence generics, might be expressed in the outward facing interfaces, and thus making them mostly redundant in a single service. Sharing implementations becomes less important at this scale, as it creates problems on it own. Hiring and onboarding masses of juniors are commonly a problem here.
Hence, except for networking/systems styled solutions, Go might also be well suited for very large organizations with endless hiring needs, and a desire to look more modern.
You can also see this in the testing story. Go is very focused on unit testing which makes sense when you are one cog in a giant machine. But if you're writing something standalone the friction to write end to end integration tests is what turned me off.
That doesn't mean the code above is good, just that the lack of generics sometimes makes copy-pasting in Go inevitable.