Go

What are self-referential (recursive) constraints and generic interfaces? Give an example.

Question 128HardGo 1.22 to 1.25

An interface can itself have type parameters. That lets a constraint refer to the type being constrained, similar to F-bounded polymorphism or Java's Comparable<T>. It is useful when a method must take or return the same concrete type.

type Lesser[T any] interface {
    Less(T) bool
}

// T must have a method Less(T) bool
func MinOf[T Lesser[T]](xs ...T) T {
    m := xs[0]
    for _, x := range xs[1:] {
        if x.Less(m) {
            m = x
        }
    }
    return m
}

type Version struct{ Major, Minor int }

func (a Version) Less(b Version) bool {
    return a.Major < b.Major || (a.Major == b.Major && a.Minor < b.Minor)
}

fmt.Println(MinOf(Version{1, 4}, Version{1, 2}, Version{2, 0})) // {1 2}

A generic interface with only methods, such as type Store[K comparable, V any] interface{ Get(K) (V, bool); Put(K, V) }, can also be used as an ordinary interface type once it is instantiated (var s Store[string, int]). That makes it useful for dependency injection in repositories and caches.

Gotcha: Less(Lesser[T]) bool would be a different signature. The parameter type must be exactly T.

More on Generics

All 36 Generics questions