This has to do with how Go handles dynamic typing via interfaces and how structs fit into that.
When a function takes an interface type as an argument, and you pass a pure struct to it, it creates a wrapper around it (this is the allocation referred to in your quote) which is simply a pair of pointers, one being a type/vtable pointer and the other being a pointer to the struct's data.
Doing it this way allows code to do run-time type inference as well as allow interface extension implicitly (that is, implementing an interface is done by implementing its methods, and you don't have to explicitly type it like ByteReader extends Reader"). Since you only pay this cost if you use it, a lot of fast-path code will use structs exclusively if it can.
How do generics change this? Can a type bound on a generic work like a static interface implementation specification, and recover the cost of wrapping the struct?
You can declare generic structs and generic functions, and get monomorphized copies (not erased to "any") of each function for all concrete types used. You can't look them up by reflection. You can't declare generic methods, and still can't overload methods by type.
> get monomorphized copies (not erased to "any") of each function for all concrete types used
That's not exactly true. You get one concrete function for all generic pointer types for instance.
Generic functions take a hidden paramater called a dictionnary, which is fairly similar to vtable, since it contains type information and pointers for all methods of the generic type that the function calls.
So methods on generic types are still performed through an indirection.
Thanks, had not seen that before. It's odd that they came close to reimplementing method dispatch for builtin types, but didn't surface it for developers.
When a function takes an interface type as an argument, and you pass a pure struct to it, it creates a wrapper around it (this is the allocation referred to in your quote) which is simply a pair of pointers, one being a type/vtable pointer and the other being a pointer to the struct's data.
Doing it this way allows code to do run-time type inference as well as allow interface extension implicitly (that is, implementing an interface is done by implementing its methods, and you don't have to explicitly type it like ByteReader extends Reader"). Since you only pay this cost if you use it, a lot of fast-path code will use structs exclusively if it can.