Skip to main content
In Go, interface implementation is implicit. A concrete type automatically satisfies an interface if its method set is a superset of the interface’s method set. This means the concrete type must include at least all the methods declared by the interface, and those specific method signatures (name, parameters, and return types) must match exactly. There is no explicit declaration of intent, such as an implements keyword. The relationship between the type and the interface is established entirely through structural typing and is verified by the compiler.

Mechanics of Implicit Implementation

To implement an interface, a type must define the required methods. The concrete type is permitted to have additional methods not defined by the interface, but it must possess the exact signatures of the interface’s methods to satisfy it.
The compiler enforces this relationship only when a concrete type is assigned to a variable of the interface type, passed as an argument to a function expecting the interface, or returned from a function returning the interface.

Method Sets and Receiver Types

The most critical technical constraint of Go’s implicit implementation revolves around method sets and receiver types (value vs. pointer). The method set of a type determines which interfaces it implements.
  • The method set of a value type T consists only of methods declared with a value receiver (t T).
  • The method set of a pointer type *T consists of methods declared with both a pointer receiver (t *T) and a value receiver (t T).
If an interface is implemented using a pointer receiver, the value type does not implicitly implement the interface.

Static Interface Assertions

Because implementation is implicit, a type might accidentally drop support for an interface if a method signature is altered. To enforce a strict compile-time check without relying on usage in the business logic, Go developers use a static assertion using the blank identifier (_).
In this construct, (*ImageProcessor)(nil) creates a typed nil pointer, which is then assigned to the blank identifier of the interface type Processor. This incurs no runtime overhead while guaranteeing structural compliance at compile time.
Tired of Poor Go Skills? Fix That With Deep Grasping!Learn More