Implementing interfaces

April 12, 2023

Basic interfaces

More than one type may implement an interface. For instance, if two types S1 and S2 have the method set

func (p T) Read(p []byte) (n int, err error)
func (p T) Write(p []byte) (n int, err error)
func (p T) Close() error

(where T stands for either S1 or S2) then the File interface is implemented by both S1 and S2, regardless of what other methods S1 and S2 may have or share.

This is the formal definition of Go’s version of Duck typing, which we’ve already discussed.

The explanation continues…

Every type that is a member of the type set of an interface implements that interface. Any given type may implement several distinct interfaces. For instance, all types implement the empty interface which stands for the set of all (non-interface) types:

interface{}

For convenience, the predeclared type any is an alias for the empty interface.

It’s not always obvious which types implement a given interface, and this can trip up many newcomers. Some IDEs will let you find types that implement a given interface, but for some common interfaces this is next to worthless. Consider perhaps the most common interface type, the io.Reader. There are dozens of implementations of this interface in the standard library alone. Likely hundreds or thousands in any reasonably sized project.

And most types don’t overtly advertise that they satisfy any particular interface. Consider the os.File type. This type has a number of methods defined on it: Close() error, Chdir() error, Name() string, Read([]byte) (int, error), and many others.

But what interfaces does it implement? Well, several, actually. It’s an io.Reader by virtue of implementing the Read() method. It’s also an io.ReadCloser because it implements both the Read() method and the Close() method. It’s also a an io.Writer and io.WriteCloser, and even a io.ReadWriteCloser, and many others. It can even implement user-defined interfaces. Do you want a ChdirReader interface?

type ChdirReader interface {
  Chdir() error
  Read([]byte) (int, error)
}

Fine, create that type, and os.File will automatically implement it, because it has those methods.

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

Share this