Interfaces don't contain interfaces

April 25, 2023

As we learned recently, Go interface elements may contain a type term of a non-interface type. It’s worth re-iterating that these are non-interface types.

In particular, as the spec states:

General interfaces

By construction, an interface’s type set never contains an interface type.

That is to say, that the following is invalid:

type interface foo {
  /* some interface elements */
}

type interface bar {
  foo
}

Actually, I lied. That’s not invalid. It’s a case of embedding. But the point is, putting the name of an interface inside of an interface like that does not work as putting the name of a type, such as int or a struct, in an interface.

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

Share this

Related Content

Underlying types

We’ve made it through the complete list of types in Go. Now we’re going to dig into some of the fundamentals, with a tour of general “Properties of types and values”. Properties of types and values Underlying types Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself. Otherwise, T’s underlying type is the underlying type of the type to which T refers in its declaration.

Restrictions on underlying type terms

General interfaces … In a term of the form ~T, the underlying type of T must be itself, and T cannot be an interface. type MyInt int interface { ~[]byte // the underlying type of []byte is itself ~MyInt // illegal: the underlying type of MyInt is not MyInt ~error // illegal: error is an interface } Once again, the spec examples are pretty well explained. TL;DR; the ~ prefix must always be associated with an underlying data type.

Interface examples with type elements

Let’s look at some interface examples from the spec: General interfaces … // An interface representing only the type int. interface { int } // An interface representing all types with underlying type int. interface { ~int } // An interface representing all types with underlying type int that implement the String method. interface { ~int String() string } // An interface representing an empty type set: there is no type that is both an int and a string.