Go has always had some challenges regarding polymorphism. Its type system and naming rules just made some things difficult. For example, say your code did a lot of sorting and you frequently needed a LessThan functionality. Now every structure, even in a single package, could implement a method named LessThan with its own receiver and argument type and you are fine. Very polymorphic. But if you want a LessThan function for different types, you’re only allowed one function named LessThan in a given package. You’ll basically have to use naming variations (LessThanInt, LessThanString, etc.).
Generics Helped
With the addition of generics now you had the ability to write something like:
func LessThan[T constraints.Ordered](a T, b T) bool {...}
Which allows functions to be more polymorphic like methods.
But Not Always
Say you want to implement a widely recognized concept like Map, which takes two types (A, B) and a transform function (FN) and maps A to B using FN. You immediately hit a snag with methods and with Go’s generics:
type Foo[A any] struct {}
// Maybe?
func (f *Foo[A, B])Map(a A, func(A) B) Foo[B] {...}
// Or maybe?
func (f *Foo[A])Map[B any](a A, func(A) B) Foo[B] {...}