Generic methods

July 28, 2023

Type definitions

A generic type may also have methods associated with it. In this case, the method receivers must declare the same number of type parameters as present in the generic type definition.

// The method Len returns the number of elements in the linked list l.
func (l *List[T]) Len() int  { … }

This probably needs further explanation. Or an example. It did for me.

Let’s look at a simple generic type:

type Thing[T any] struct {
	value T
}

Now you might think you could define a method on this type as so:

func (t *Thing) Foo() { ... } // compilation fails: cannot use generic type Thing[T any] without instantiation

But what we’ve just read says this doesn’t work. You must inclue the correct number of type parameters (in this case one) in the method definition:

func (t *Thing[T]) Type() string { // valid
	return fmt.Sprintf("%T", t.value)
}

But why? Perhaps to distinguish between a non-generic type of the same name? Nope, that’s invalid…

type Thing[T any] struct {
	value T
}

type Thing struct { // compilation fails: Thing redeclared in this block
	value any
}

Well, you can actually use the type parameter within the method. Here’s a re-implementation of my earlier Type() method:

func (t *Thing[T]) Type2() string {
	var x T
	return fmt.Sprintf("%T", x)
}

See this example on the playground

Quotes from The Go Programming Language Specification Version of December 15, 2022

Share this

Related Content

Type parameters in method definitions

Yesterday we saw that when a method is defined on a generic type, the receiver must include type parameters. Now for all the relevant details: Method declarations … … Syntactically, this type parameter declaration looks like an instantiation of the receiver base type: the type arguments must be identifiers denoting the type parameters being declared, one for each type parameter of the receiver base type. The type parameter names do not need to match their corresponding parameter names in the receiver base type definition, and all non-blank parameter names must be unique in the receiver parameter section and the method signature.

Methods on generic types

Ready to dive back into generics, this time with regard to methods? Great, ‘cause here we go! Method declarations … If the receiver base type is a generic type, the receiver specification must declare corresponding type parameters for the method to use. Okay. Before we continue, let’s make sure we all know exactly what we’re talking about. What does it mean for a receiver base type to be a generic type?

Final thoughs on type parameter declarations

Are you as curious about Fuzzing in Go as I am? On Monday’s live stream, I’ll be live coding my way through John Arundel’s 4-part series on Go Fuzzing. I hope you’ll join me! Two more small points before we move on from type parameter declarations… Type parameter declarations … Type parameters may also be declared by the receiver specification of a method declaration associated with a generic type. No surprises here.