iX 6/2018
S. 130
Praxis
Programmiersprachen
Aufmacherbild

Go-Tutorial, Teil 2: Feinheiten des Typensystems

Go for it!

Die Programmiersprache Go erlaubt dem Programmierer viel Flexibilität und eine genaue Kontrolle darüber, wie sich eine Anwendung verhält. Das Beispiel eines kleinen Monitors für GitHub-Events zeigt, wie elegant eine Go-Applikation sein kann.

Der erste Artikel dieses dreiteiligen Tutorials stellte bereits viele wichtige Bausteine für Anwendungen in Go vor: verfügbare und zusammengesetzte Typen, Funktionen, Interfaces und Methoden. Doch ein Programm ist mehr als seine Einzelteile. Es benötigt einen guten Aufbau, und die betrachteten Bausteine müssen sinnvoll eingesetzt werden. Anhand eines Beispiels geht die Reise in die Welt von Googles Sprache weiter.

Entstehen soll ein kleiner Monitor für GitHub-Events, der „GitHub Progress Monitor“. Er fragt die Ereignisse unterschiedlicher Repositories regelmäßig ab, wertet sie aus und stellt die Ergebnisse zur Abfrage bereit. Das Ganze wird so ausgelegt, dass der Anwender später leicht eigene Auswertungen und Ausgaben hinzufügen kann. Das Beispiel soll zeigen, wie sich mit einer so technisch erscheinenden Sprache wie Go auch elegante Lösungen entwickeln lassen.

Das System besteht aus vier Blöcken. Neben dem Daemon im Package ghpmd für das eigentliche, später zu startende Programm wird es drei Packages geben, die aufeinander aufbauen:

 github als API für den Zugriff auf GitHub,

 analyze für die Analyse der Daten und

 output für die unterschiedlichen Ausgabeformen.

Dabei bilden die Packages einen Mix aus reinen Datentypen, Funktionen, Interfaces und komplexen Typen. Hier wird der Pragmatismus der Sprache Go deutlich. Es kommen nicht nur Funktionen und nicht nur Objekte zum Einsatz. Vielmehr bestimmt der Einsatzzweck eines Typs die Form seiner Implementierung.

Schnittstelle mit Freiraum

Für den Abruf der Informationen von GitHub nutzt das Beispiel die Version 3 der API. Sie arbeitet mit einer einfachen REST-Schnittstelle und liefert JSON als Ergebnis zurück. Dies sind beides Felder, in denen sich Go wohlfühlt und für die die Sprache in der Standardbibliothek alle notwendigen Packages mitbringt. Wesentlich sind net/http für den Webzugriff und encoding/json für das Unmarshalling der empfangenen JSON- in Go-Strukturen. Inzwischen stellt GitHub auch die Version 4 der API auf der leistungsfähigen Basis von GraphQL [1] bereit, doch ist dies nicht Inhalt des Artikels.

Listing 1: RepoEventor

type RepoEventor struct {
    owner string
    repo string
}

func NewRepoEventor(o, r string) ⤦
 *RepoEventor {
    return &RepoEventor{
        owner: o,
        repo:  r,
    }
}

Die konkreten Informationen im Beispiel sind Events individueller Repositories. Hierzu werden initial Owner und Repository als Parameter benötigt, weitere Optionen kommen später hinzu. Den Beginn machen daher der RepoEventor als Typ und sein Konstruktor (Listing 1).

In dieser noch sehr einfachen Variante wird deutlich, dass Go keinen klassischen Konstruktor als Teil der Sprache kennt. Vielmehr nutzt es reguläre Funktionen, die die Instanzen des gewünschten Typs erzeugen und zurückgeben. Im vorliegenden Fall ist das noch einfach, doch kann es mit Parameterauswertung oder dem Start von Goroutinen auch aufwendiger werden. Eine besondere Konvention hat sich bei spezialisierten Packages mit nur einem exportierten Typ ergeben. Hier wählt der Entwickler den Package-Namen passend zum Typ und der Konstruktor heißt der Lesbarkeit wegen New(). So liefert etwa l := list.New() aus der Standardbibliothek eine neue Liste zurück.