Komposition für Anfänger

Ein ganz einfaches Beispiel soll zeigen, was alles mit der Komposition in Go möglich ist. Nehmen wir mal folgendes Beispiel an.

Es gibt einen Typ A, welches eine Methode Print() besitzt. Typ B hat in seiner Definition auf Typ A im Bauch. Wäre Go nun objekt-orientiert, würde man auch sagen, B erbt alles von A. Dadurch kann eine Instanz von B eigentlich auch alles was A kann.

Diese Erkenntnis ist erstmal nichts besonderes. Auf die gleiche Weise wie B definieren wir nun Typ C. Für Typ C ist nun aber die Funktion Print() nicht so wie wir das benötigen. Also definieren wir für C die Methode einfach neu. Wenn nun eine Instanz von C die Methode Print() aufruft, dann wird unsere neue Methode dafür verwendet.

type A struct {
}

func (a *A) Print() {
	fmt.Println("AAAA")
}

type B struct {
	A
}

type C struct {
	A
}

func (c *C) Print() {
	fmt.Println("CCC")
}

Das ganze auch noch einmal im Playground: https://play.golang.org/p/Z0TprdJZ7_

Auf den ersten Blick ist diese Logik nichts besonderes. Aber wenn man z.B. aus einem Java Umfeld kommt, dann ist es anscheinend nicht leicht, zu erkennen, wann man dieses Pattern gut anwenden kann. Insbesondere beim Testen ist diese Logik hilfreich.

Im folgenden Beispiel lässt sich so ein Typ anlegen, welcher sich alle Queries merken kann und keinen Einfluss auf die DB nimmt.

type MockDB struct {
	externDBPackage.DB
	Queries []string
}

func (mdb *MockDB)  Query(query string, args ...interface{}) (*Rows, error) {
	mdb.Queries = append(mdb.Queries, query)
	// Do something
	return &Rows{},nil
}

Ähnliche Lösungen sind möglich, wenn man z.B. vermeiden möchte, dass man in seinen Tests auf das Filesystem schreibt.

comments powered by Disqus