are Go generics more like C++ or more like Java?

1,205 views
Skip to first unread message

Jason E. Aten

unread,
Feb 23, 2022, 3:41:14 PM2/23/22
to golang-nuts
Back in 2009, Russ wrote a blog on generics, talking about the tradeoffs in providing generics:

"The generic dilemma is this: do you want slow programmers, slow compilers and bloated binaries, or slow execution times? " -- https://research.swtch.com/generic

I haven't had the bandwidth to follow the generics detailed discussions.  I was just curious, at a high level, for creating a mental model of Go's generics: which approach was taken?

Thanks!

J

Jason E. Aten

unread,
Feb 23, 2022, 7:50:52 PM2/23/22
to golang-nuts
There was nothing in the tutorial, and I see that the design declines to commit, permitting "the implementation to decide", per https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#implementation

So I was just curious which way the implementation ended up going.

Eno Compton

unread,
Feb 24, 2022, 12:40:57 PM2/24/22
to golang-nuts
Based on what I've seen, the implementation of generics *may* slow down the compilation.

Markus Heukelom

unread,
Feb 25, 2022, 5:13:01 AM2/25/22
to golang-nuts
I think the consensus in the Go community is to refrain from comparing Go language features with other programming languages. Rationale ~:

- it is highly contentious
- it is very difficult to answer, it's like asking "is purple more blue or more red"
- no matter the answer, it will not help you a lot to write better programs or be more productive in Go

However, maybe your real question is more like "what are/were the guiding principals for generics in Go?".   As far as I understand, generics in Go follow the same principles as other language features in Go:

- compilation should be very fast, but trade-offs are allowed so it does not need to be maximally fast
- language features should be as orthogonal as possible, but trade-offs are allowed so they don't need to be maximally orthogonal
- it should be a simple as possible but no simpler
- ... 

For generics this has resulted in:

- exotic use-cases are not supported (for example having an integer *constant* as *generic parameter*, such as you see in C++ fixed size matrix templates, is not supported)
- it must be possible to express that T is comparable (f.e. min(a, b T) T must be possible to write)
- it must be possible restrict T to a concrete list of types 
- it must be possible to restrict T to a type with method set that equals that of some interface (I *personally* think this violates the principle of orthogonality too much and will lead to confusion and design debate)  

Of course, neither list is exhaustive and is only my personal understanding of things.

-Markus

Markus Heukelom

unread,
Feb 25, 2022, 5:15:47 AM2/25/22
to golang-nuts
Correction:

- it must be possible to express that T is comparable (so that you can use map[K]V, were K must be comparable)
- it must be possible restrict T to a concrete list of types (f.e. min(a, b T) T must be possible to write)

Ugorji Nwoke

unread,
Feb 26, 2022, 6:51:46 PM2/26/22
to golang-nuts
To your direct questions, the answer is a mix of both: C++ style where the generic block is a template and code is essentially generated for each type known at compile time with static dispatch, and java-like where it is similar to an interface call with dynamic dispatch. The compiler will strike the right balance of binary size, compile time and execution speed. To follow its heuristics rules (which will likely not be formally published to prevent people from depending on it), you might have to stay close to the development for that.

robert engels

unread,
Feb 27, 2022, 12:33:35 PM2/27/22
to Ugorji Nwoke, golang-nuts
I disagree that it wont be formally published - or at least have knobs to turn to control it - otherwise it will be nearly impossible to make the determination of when your generic’s usage will result in a performance penalty. This probably won’t matter for 95% of the code - but it if does matter - your only solution would be to always avoid generics and roll your own - which defeats the purpose.

I can see build labels controlling the generation options.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/8edf65b3-f499-4446-908e-8e35d3070739n%40googlegroups.com.

Axel Wagner

unread,
Feb 27, 2022, 1:05:09 PM2/27/22
to robert engels, Ugorji Nwoke, golang-nuts
On Sun, Feb 27, 2022 at 6:33 PM robert engels <ren...@ix.netcom.com> wrote:
I disagree that it wont be formally published - or at least have knobs to turn to control it - otherwise it will be nearly impossible to make the determination of when your generic’s usage will result in a performance penalty.

This doesn't seem substantially different from escape analysis. Where there is also no spec or any other formal description, but just a flag to log decisions.
I would expect generics to work similar in that regard.
 

robert engels

unread,
Feb 27, 2022, 5:34:53 PM2/27/22
to Axel Wagner, Ugorji Nwoke, golang-nuts
I think that would be a miss. The size/speed trade-off cannot often not be made accurately when viewed in isolation. E.g. it may be the best course of action to generic 16 different implementations in some cases, but as a general rule exploding every implementation x16 is probably unwise.

Being able to turn knobs on these decisions will be critical to achieving optimal overall application performance.

Kevin Chowski

unread,
Feb 27, 2022, 9:53:22 PM2/27/22
to golang-nuts
I think it would be neat for the Go compiler to natively support profiles for profile-guided optimization to help make decisions about code generation for generics (and specialization for interfaces, for that matter). And also other random optimizations, for example inline aggressiveness. If you can manage a semi-realistic load test, or if you can (sometimes) profile in production, then no one needs to fiddle with knobs to get pretty good optimization decisions. Plus, if you can set something up regularly re-profile, then you can ensure that optimization decisions don't go stale like might happen with static knobs.

Then, someone could write a profile generator based on knobs or in-source annotations, if they really wanted to :)

Axel Wagner

unread,
Mar 1, 2022, 2:02:20 AM3/1/22
to golang-nuts
FYI, a design doc was published, describing the chosen approach for Go 1.18.
I thought it might be interesting for people reading/posting to this thread to get an authoritative answer to OP's question.

Ali Altun

unread,
Mar 17, 2022, 3:05:21 PM3/17/22
to golang-nuts

Go - FAQ:   How do generics in Go compare to generics in other languages?


On Wednesday, February 23, 2022 at 9:41:14 PM UTC+1 Jason E. Aten wrote:

Glen Newton

unread,
Mar 17, 2022, 8:59:05 PM3/17/22
to golang-nuts
>- exotic use-cases are not supported (for example having an integer *constant* as *generic parameter*, such as you see in C++ fixed size matrix templates, is not supported)

Does a longer (but not necessarily exhaustive) list of the unsupported exotic use cases exist? This would be useful to understand all of the situations where Go generics cannot (or should not?) be used. 

Glen
Reply all
Reply to author
Forward
0 new messages