Frankly, having used Go for years, I started using generics right after they were released and I'm very happy with them so far.<p>Sure, the performance characteristics could be improved, but other than that they solve all my main pain points I wanted them to solve while being constrained enough to not result in ivory towers on every corner.<p>My main pain points having been duplicated functions for each type as well as data structures.
Two thoughts:<p>1) The failure of<p><pre><code> func (t *fishTank) fishCount() string {
return fmt.Sprintf("How many fishies? %d!", t.size())
}
</code></pre>
to work has nothing to do with generics; methods are always "removed" from types defined this way. If you want you can cast `t` to a `*container[fish]` and call it, but this is also where I would ask why "extend" rather than compose - are you gaining anything by ensuring identical layouts?<p>2) The bigger issue, that interfaces cannot require their implementations to be comparable, is <a href="https://github.com/golang/go/issues/52614" rel="nofollow">https://github.com/golang/go/issues/52614</a> and linked tickets.
Here's the way you can solve the first problem with generics in go, almost exactly as he described:<p><a href="https://go.dev/play/p/GrLYBj3N0jr" rel="nofollow">https://go.dev/play/p/GrLYBj3N0jr</a><p>The trick is to define the fish tank like so:<p><pre><code> type fishTank struct {
container[fish]
}</code></pre>
When I started using Go generics, they turned out to be completely useless for the use case I wanted to solve the most: functions to use in Go templates. Something is basic as <i>adding two numbers</i> is not solved by the core library and becomes a challenge with about a dozen numeric types. You can use a type switch and cast interface{}/any to float64 (which is a hack, but one that works in practice). What you can't do is use generics, because they require instantiation at compile time, which cannot happen in templates, because those are dynamic. Extremely disappointing.<p>Another disappointing thing is the fact that Go type inference is not good enough to have syntactically compact lambda functions. So now, even though it's possible to write code that does filter-map-reduce kind of stuff, it's verbose, slow to write and hard to read.
Adding a type system to an existing language that was never intended to have that type system is not simple. And in Go, the language seems designed to largely eject its type system at the earliest opportunity that doesn't negatively impact the compiler. This will naturally constrain the capabilities of the generic programming constructs, much as it did in Josh Bloch's Java generics implementation.<p>Go is going to be torn between the minimalism of its creators, and the desires for modern capabilities expressed by its vocal user base. If this were a movie, it would be "A Beautiful Mind".
Not a Go developer but i've been playing with Go for a toy project, really just to learn it. I had a tiny play with generics in Go when i needed a "min(int, ...int) int" func<p><pre><code> // --- There's no int min() in stdlib -----------------------------------------
// Option 1. use math.Min() which is defined for float64, benchmarks comparing this with Option 2 & 3:
// BenchmarkMinImplementations/math.Min-8 261596238 4.282 ns/op
// BenchmarkMinImplementations/minGeneric-8 588252955 2.037 ns/op
// BenchmarkMinImplementations/minVariadic-8 413756245 2.827 ns/op
// Option 2. Generics in Go 1.18, this is generic over int and float but can't support a variadic "b"
func minGeneric[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}
// Option 3. I was aiming for a lisp-style (min 1 2.3 -4) and this is variadic but it can't also be generic in 1.18
func minIntVariadic(a int, bs ...int) int {
for _, b := range bs {
if b < a {
a = b
}
}
return a
}
</code></pre>
Coming from Java there's less to get your head around, e.g. super vs. extends isn't a thing here but otherwise similar.
Hey Tim, a long time ago I came to your office in Vancouver to talk about Ruler. Quamina seems very similar.<p>Are you learning Go with a familiar project? or is there another motivation for Quamina?
Go is my main language but it keeps disappointing me in it's lack of implementation tuning detail. Generics are just a code generator that, given it's poor performance for things like functional programming, makes it surprisingly of little use.<p>Go is a kitchen full of dull knives. It is good for layers of communication where you call other microservices to perform the heavy lifting, but not much else.