No, they don't. They didn't before generics and they do even less now.
You can tell this is an accusation thrown around by non-Go programmers because frankly, throwing around a lot of interface{} was always really inconvenient. It's not something the language trains you to do... it's something you get punished for, really quite hard.
I’ve noodled around with generating review-ready Go from CL (because macros), but it’s hard to flatten subexpressions (like multiple-value-bind around a call that returns a value and an error) into blocks of statements that assign to new temp vars, and I couldn’t expect arbitrary CL to just work, it’d be more of a CL-flavored DSL for generating loops and error handling.
Anything that made programming easier in the last 30 years.
I miss Hindley Milner type inference, ADTs, default immutability, sane error handling, pattern matching, and functional collection manipulation.
I'm not even mentioning the time it took to add generics to the language, which should've come from the beginning, and we got a bad implementation of it.
Not saying that it HAS to have all of this, but at least 1 or 2 things of that list would already make Go have much better ergonomics.
Go has no excuse since it's a relatively new programming language, and it could've got some of those from the start.
TBH, it sounds like you want a functional language (type inference, pattern matching, collection manip), of which there are many. GO is not such a language. But then you want ADTs, which aren't really functional. I'm not sure you can have both in a clean way. The closest you might get is a multi-paradigm language that tries to allow both, like C++.
Default immutability is great in a language like Rust where it's designed from the ground up to warn you as much as possible at compilation when something is wrong. You can rely on the compiler a lot. But adding default immutability to a language that isn't designed around the same concepts seems odd. You don't gain the same kind of benefits, but you do have to deal with the tedium. Worst of both worlds, in my view.
Not exactly. I don't think Go should have ALL those, but some would be extremely helpful. That's just a wishlist.
There are some examples of languages that have a nice blend of functional features built in that are not fully functional languages, and the developer experience is fantastic (e.g. C#, Typescript, Kotlin, Swift, Java 11+)
They could've improved the developer experience, but they made some kind of C+- with easier concurrency.
And I find it all sad because Go ticks many of my boxes for a "perfect" general-purpose programming language.
> But then you want ADTs, which aren't really functional.
Pretty sure by ADTs, GP means "algebraic data types". These are very much functional, at least in the sense that they're a standard feature of statically typed FP (at least I know of no such language that doesn't have them).
ADT also sometimes stands for "abstract data type", which is something different. Although I wouldn't call them incompatible with FP either, Haskell typeclasses can express abstract data types, for example.
If people would stick to common generic data structures (like a map/list that can handle any datatype), i'd be fine with abstractions.
But some people have a tendency to play code golf with their codebases.
I have, for example, encountered a "generic data structure" that looked like a normal linked list on the surface. BUT, it actually sorted the largest three items in the first 3 cells and the average in the 4th.
That was multiple days of work wasted because someone decided to be cute with their data structures. And that wasn't even the only one of such "generic" monstrosities in the code.
Generics (and other abstractions) are not the root cause. Go was a pragmatic defence against mediocre developers. The majority of developers are mediocre by definition, and will abuse _any_ abstractions to create Rube Goldberg contraptions and monstrosities.
Well there is a valid point of abuse in abstractions. The ruby world is a disaster because of the power provided combined with people reaching out to all sorts of abstractions the entire time for purely experimental reason.
It's true that applicative code shouldn't need generics in probably more than 90% of the times, however the lack of it affects library authors quite heavily
No, it's relative. For the top 5% - 10% of developers, generics are a useful tool for doing their job efficiently. For the bottom 50% of developers, generics are complex and confusing, and only provides more footguns.
For 0.5%-1% C++ is a powerful tool which allows to quickly (thanks to rich abstractions) to write high-performance code.
For merge mortals it is a tool hard not to misuse full of hidden traps and debugging of code written even by the very best developers (surprise - it has bugs too) is a challenge.
Go just did a step towards C++, even if a tiny one.
And the top 1% of developers know that you are most productive when you stick to the simplest primitives ;)
I jest, but I also don't. All the best developers I know strongly prefer footgun-free libraries and primitives. The advantage is that you don't _need_ to spend brain cycles checking and double checking that it was written correctly, and when you want to make changes you don't need unwind an elaborate abstraction to stretch it further.
In martial arts (I'm a second degree black belt), the third move you learn is the round house kick (turned leg kick - the first two moves are the punch and the straight leg kick). At the olympic level, 70% of all points are scored using a roundhouse kick.
The other funny thing about the roundhouse kick is how much you can learn from watching someone do a single one. You can tell the difference between someone with 2 years of experience and 3 years of experience, and you can _also_ tell the difference between someone with 15 years of experience and 20 years of experience.
The point of this story being that masters are masters not because they can do elaborate techniques, but because their command over the simplest techniques is superlative.
I've found in life that this applies to pretty much everything. Martial arts, programming, painting, cooking, and effectively any task that definitively has some people who are better than others.
Generics use the type system to make the compiler check the code for you. It makes the code easier to understand, more correct, and concise if you use them as they were intended. It avoids tedious and error prone duplication of logic. Create ONE efficient debugged implementation and reuse it as much as possible. The crappy workarounds for generics introduce their own complications and issues.
But I know what you mean. I've worked on Scala code for years and seen less mature developers over-engineer things and get way too clever with the type system. Scala is a really practical and powerful industrial language that requires some maturity to use the abstractions sparingly. It's only good for the top 5% of developers.
However, Go doesn't have such a powerful type system. It looks like the Go designers implemented relatively simple generics. You have to draw the line somewhere. If simple Go generics are too confusing and complicated then that developer should probably find another job, as generics are a basic concept in programming. The Go designers are pragmatic people, and they've decided that relatively simple generics will make things easier in mainstream commercial codebases.
If anything generics will make go code simpler.
No more copy pasting everywhere and the possibility of making useful collection methods like map, filter and reduce.
https://coalton-lang.github.io/20260424-mine/ and https://lem-project.github.io/