liveBook · Manning

Implicit interface satisfaction

As explained in Go by Example

An implicit interface is a Go interface that a type satisfies automatically by implementing all of the interface's methods without an explicit declaration.

In Go, a type satisfies an interface automatically when it implements every method the interface requires. The type never declares that relationship. A function can accept an interface and receive any matching concrete type, while the compiler rejects types that lack a required method. This combines flexible substitution with compile-time checking. section 1.5.2

Figure 1.7 The function expects a type that implements the runner interface—any type with a run() method. You can pass either of these types to the function interchangeably because each has a run() method and implicitly satisfies runner.
A white rectangular sign with black text

AI-generated content may be incorrect.

A function needing runner can accept either concrete type because both provide run, despite neither naming runner. section 1.5.2

This lets code begin with concrete types instead of speculative abstractions. Introduce an interface when a real consumer needs to accept more than one implementation, or when a dependency must be replaced in a test. Interfaces add indirection and maintenance, so each one should represent a genuine behavioral boundary. section 8.8.1 section 10.4

Keep implicit interfaces useful and focused:

  • Define the interface where its consumer needs a behavior, rather than requiring the provider to announce an implementation. section 10.4.1
  • Include only the methods currently required. Small interfaces are easier to satisfy, compose, understand, and keep stable as providers evolve. section 10.4.1
  • Use a fake that implements the needed methods when testing code against an external API, even if that API provides no interface. section 1.5.3

Test a payment dependency without live requests

Code that charges through an external payment API can accept a local Charger interface containing only Charge. A test-only FakeCharger implements Charge and can be passed to the same code. The production API can also be used whenever it has that method, so an absent provider-defined interface does not block testing. section 1.5.3

Adapt an HTTP transport with a function type

A function type can satisfy http.RoundTripper by declaring a RoundTrip method that calls its function receiver. Convert a closure to that type, assign it to http.Client.Transport, and provide controlled requests or responses while testing. A struct is not required; implementing RoundTrip is sufficient. section 7.5.1

Let the REST consumer own Shortener

A REST package can declare a Shortener interface with only Shorten and accept any matching provider, including a SQLite-backed shortener. The provider need not import or mention the consumer’s interface. Keeping the boundary local prevents provider-specific methods from becoming requirements for the consumer. section 10.4.1

Figure 10.6 The consumer (rest) owns the interface rather than the provider (sqlite).
A diagram of a software system

AI-generated content may be incorrect.

The consumer-owned interface boundary lets the REST package depend on Shorten while the SQLite provider remains unaware of that interface. section 10.4.1

How Go by Example covers it

How deep it goes
Explains automatic satisfaction through runnable patterns, then applies it to fakes, HTTP transports, and consumer-owned contracts.
Examples
Uses runner implementations, a fake payment charger, a function-backed RoundTripper, and REST-to-SQLite shortening.
What you can do after
Apply it via small consumer-owned interfaces, fake dependencies, and function adapters for testable integrations.
How it connects
Connects interfaces with duck typing, dependency injection, testing, higher-order functions, interface embedding, and type assertions.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go by Example. The section links point to the parts of the book it draws on.