Type constraints

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!](https://youtube.com/live/VKV-sFFeSQw Type constraints A type constraint is an interface that defines the set of permissible type arguments for the respective type parameter and controls the operations supported by values of that type parameter. TypeConstraint = TypeElem . If the constraint is an interface literal of the form interface{E} where E is an embedded type element (not a method), in a type parameter list the enclosing interface{ … } may be omitted for convenience:


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.


Resolving type parameter ambiguities

First today, one rather mundane sentence from the spec… Type parameter declarations … Just as each ordinary function parameter has a parameter type, each type parameter has a corresponding (meta-)type which is called its type constraint. Followed by a bit of WTF… A parsing ambiguity arises when the type parameter list for a generic type declares a single type parameter P with a constraint C such that the text P C forms a valid expression:


Type parameter declarations

Type parameter declarations A type parameter list declares the type parameters of a generic function or type declaration. The type parameter list looks like an ordinary function parameter list except that the type parameter names must all be present and the list is enclosed in square brackets rather than parentheses. TypeParameters = "[" TypeParamList [ "," ] "]" . TypeParamList = TypeParamDecl { "," TypeParamDecl } . TypeParamDecl = IdentifierList TypeConstraint .

Subscribe to Boldly Go: Daily

Every day I'll send you advice to improve your understanding of Go. Don't miss out! I will respect your inbox, and honor my privacy policy.

Unsure? Browse the archive.


Generic methods

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:


Circular generic types

There’s a lot to cover within type definitions! We’re several days in, and still going strong… Type definitions … In a type definition the given type cannot be a type parameter. type T[P any] P // illegal: P is a type parameter func f[T any]() { type L T // illegal: T is a type parameter declared by the enclosing function } I expect this will surprise noone. We’ve already seen that struct, array, and slice types cannot reference themselves.


Definitions of generic types

Type definitions … If the type definition specifies type parameters, the type name denotes a generic type. Generic types must be instantiated when they are used. type List[T any] struct { next *List[T] value T } We haven’t covered instantiation yet, but we will. For now, let’s just summarize: Instantiation is process by which a generic type’s type parameters are substituted with the actual type arguments to be used.


Methods aren't for "objects"

I’ll be livestreaming again today, in just a few minutes. Join me live, or watch the replay. I’ll be picking up where I left off, with my new linter project. One of the most powerful things I like about Go, is the ability to put methods on any type. Type definitions … Type definitions may be used to define different boolean, numeric, or string types and associate methods with them:


Types with methods

Type definitions … A defined type may have methods associated with it. It does not inherit any methods bound to the given type, but the method set of an interface type or of elements of a composite type remains unchanged: // A Mutex is a data type with two methods, Lock and Unlock. type Mutex struct { /* Mutex fields */ } func (m *Mutex) Lock() { /* Lock implementation */ } func (m *Mutex) Unlock() { /* Unlock implementation */ } // NewMutex has the same composition as Mutex but its method set is empty.


Type definitions

Some of the minutiae we’ve gone over about underlying types, and type identity are finally starting to come together… Type definitions A type definition creates a new, distinct type with the same underlying type and operations as the given type and binds an identifier, the type name, to it. TypeDef = identifier [ TypeParameters ] Type . The new type is called a defined type. It is different from any other type, including the type it is created from.


Alias declarations

Alias declarations An alias declaration binds an identifier to the given type. AliasDecl = identifier "=" Type . Within the scope of the identifier, it serves as an alias for the type. type ( nodeList = []*Node // nodeList and []*Node are identical types Polar = polar // Polar and polar denote identical types ) Aliases are a feature you likely won’t use frequently. You may never use it, in fact.