Skip to main content
Entwickler Themen
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

7.2.4. Interfaces

Interfaces in Go sind klein, implizit und gehören dorthin, wo Verhalten gebraucht wird – nicht dorthin, wo es implementiert wird.

Klein halten

Oft reicht eine Methode. Vorbilder in der Stdlib: io.Reader, io.Writer, fmt.Stringer. Proverbs: The bigger the interface, the weaker the abstraction und interface{} says nothing – dafür schreibt man heute any.

type Reader interface {
	Read(p []byte) (n int, err error)
}

Ein-Methoden-Interfaces heißen oft auf -er: Reader, Writer. Berühmte Methodennamen nicht mit anderer Signatur wiederverwenden.

Consumer definiert das Interface

Das Package, das Verhalten nutzt, besitzt die Interface-Deklaration. Der Produzent liefert konkrete Typen. Keine Interfaces „zum Mocken“ auf der Produzentenseite und keine Abstraktion, bevor ein realistischer zweiter Nutzer existiert.

// package consumer
type Thinger interface{ Thing() bool }

func Foo(t Thinger) string { /* ... */ }

// package producer – konkret zurückgeben
type Thinger struct{ /* ... */ }

func NewThinger() Thinger { return Thinger{} }

Accept interfaces, return concrete

Parameter dürfen Interfaces sein, die das benötigte Verhalten beschreiben. Rückgaben sind meist konkrete Structs/Pointer (error und bewusste Factories ausgenommen).

func Save(w io.Writer, data []byte) error {
	_, err := w.Write(data)
	return err
}

func NewClient(addr string) *Client { return &Client{addr: addr} }

Konkrete Rückgaben geben dem Caller die volle API; er kann den Wert trotzdem an alles übergeben, was ein kleineres Interface braucht.

Implizite Erfüllung

Es gibt kein implements. Ein Typ erfüllt ein Interface, wenn er die Methoden hat. Optionaler Compile-Check (Uber-Stil):

var _ http.Handler = (*Handler)(nil)

Keine Pointer auf Interfaces

Interface-Werte tragen Typinfo und Datenpointer selbst. *io.Reader als Parameter ist fast immer falsch – io.Reader reicht.

Receiver und Method Sets

Pointer-Receiver-Methoden gehören nur zu *T; Value-Receiver zu T und *T. Braucht man Mutation über Pointer-Methoden, Pointer speichern bzw. zurückgeben, wenn der Wert einem Interface zugewiesen wird.

Mehr zu vorzeitiger Abstraktion: 7.2.7. Einfachheit.

Diese Seite gehört zu 7.2. Clean Code.