Tech News
← Back to articles

Generic interfaces

read original related products more articles

Generic interfaces

Axel Wagner

7 July 2025

There is an idea that is not obvious until you hear about it for the first time: as interfaces are types themselves, they too can have type parameters. This idea proves to be surprisingly powerful when it comes to expressing constraints on generic functions and types. In this post, we’ll demonstrate it, by discussing the use of interfaces with type parameters in a couple of common scenarios.

A simple tree set

As a motivating example, assume we need a generic version of a binary search tree. The elements stored in such a tree need to be ordered, so our type parameter needs a constraint that determines the ordering to use. A simple option is to use the cmp.Ordered constraint, introduced in Go 1.21. It restricts a type parameter to ordered types (strings and numbers) and allows methods of the type to use the built-in ordering operators.

// The zero value of a Tree is a ready-to-use empty tree. type Tree[E cmp.Ordered] struct { root *node[E] } func (t *Tree[E]) Insert(element E) { t.root = t.root.insert(element) } type node[E cmp.Ordered] struct { value E left *node[E] right *node[E] } func (n *node[E]) insert(element E) *node[E] { if n == nil { return &node[E]{value: element} } switch { case element < n.value: n.left = n.left.insert(element) case element > n.value: n.right = n.right.insert(element) } return n }

(playground)

However, this approach has the disadvantage that it only works on basic types for which < is defined; you cannot insert struct types, like time.Time.

We can remedy that by requiring the user to provide a comparison function:

... continue reading