Boring Stack


3 Min. Lesezeit

Go, weil es sich in fünf Jahren noch gleich liest

Die Sprachentscheidung hinter jeder App, die ich baue

Das ist der erste von zehn Texten über die Entscheidungen dahinter, wie ich Software baue. Jede hat eine Zeile auf meiner Stack-Seite, und jede ist mit Absicht langweilig. Die erste Entscheidung ist die, von der alles andere abhängt: die Sprache.

Ich baue in Go.

Was ich von einer Sprache brauche

Ich leite beruflich eine IT und schreibe Software am Abend und am Wochenende. Das bestimmt, was ich brauche. Ein Projekt bleibt vielleicht drei Monate liegen. Wenn ich zurückkomme, muss ich es in Minuten verstehen, sicher ändern und noch am selben Abend ausliefern.

Ich optimiere also nicht darauf, wie schnell ich am ersten Tag Code schreibe. Ich optimiere darauf, wie schnell ich ihn am neunzigsten Tag lese.

Warum Go passt

Ein statisches Binary. go build erzeugt eine einzige Datei, die die ganze App enthält: den Webserver, die Templates, die Datenbankmigrationen, sogar CSS und Schriften, wenn man sie einbettet. Deployen heisst eine Datei kopieren. Es gibt keine Laufzeitumgebung auf dem Server und keinen Ordner mit Abhängigkeiten, der synchron bleiben muss.

Eine Standardbibliothek, die das Web abdeckt. HTTP-Server, Routing, JSON, Templates, Kryptografie, Tests: alles ist in der Standardbibliothek, gepflegt vom Go-Team, mit einem Kompatibilitätsversprechen. Viele Apps brauchen darüber hinaus nur eine Handvoll Abhängigkeiten.

Code, der überall gleich aussieht. gofmt legt die Formatierung für jedes Go-Projekt der Welt fest. Die Sprache hat wenige Features und fast keine Magie. Go-Code von jemand anderem sieht sehr ähnlich aus wie meiner, auch wie der von mir vor fünf Jahren.

Fehler, die man sieht. Die Fehlerbehandlung in Go ist bekannt für ihre Wiederholung: if err != nil nach jedem Aufruf, der scheitern kann. Ich mag das inzwischen. Jede Stelle, an der etwas schiefgehen kann, ist im Code sichtbar, genau dort, wo es passiert. Nichts wird drei Schichten weit in einen Handler geworfen, der nicht weiss, was er damit tun soll.

Langweilige Upgrades. Dank des Kompatibilitätsversprechens kompiliert Code, der für Go 1.0 geschrieben wurde, heute noch. Ein Go-Upgrade ist meistens eine einzige geänderte Zeile. Vergleich das mit Ökosystemen, in denen eine neue Hauptversion des Frameworks heisst, die halbe App neu zu schreiben.

Was es kostet

Go hat auch Nachteile.

  • Es ist wortreich. Manches braucht mehr Zeilen als in Python oder TypeScript. Das nehme ich in Kauf, weil die zusätzlichen Zeilen von der lesbaren Sorte sind.
  • Das Ökosystem ist für manches kleiner. Für Web-Apps ist das selten ein Problem. Für Data Science oder Machine Learning ist Go nicht die naheliegende Wahl.
  • Generics kamen spät und sind bewusst beschränkt. Wer ausdrucksstarke Typsysteme liebt, findet Go schlicht. Schlicht ist der Punkt.

Auch die Werkzeuge fixieren

Die Go-Version zu fixieren reicht nicht. Werkzeuge wie templ (für Templates) und golangci-lint (fürs Linting) erzeugen oder prüfen Code, und eine andere Version des Werkzeugs kann ein anderes Ergebnis liefern. Ein separat installiertes templ kann Aufrufe von Funktionen erzeugen, die die fixierte Bibliotheksversion nicht kennt, und ein global installierter Linter, der mit einem älteren Go gebaut wurde, kann an neuerem Code scheitern.

Seit Go 1.24 kann go.mod Werkzeuge mit einer tool-Direktive fixieren, und go tool templ startet genau diese Version. Jedes Werkzeug in meinen Projekten läuft über go tool. Derselbe Commit baut auf jedem Rechner gleich, und genau das heisst langweilig.

Wann ich anders entscheiden würde

Wenn ein Team eine andere Sprache gut kennt und den Betrieb dafür schon hat, würde ich ihm Go nicht aufzwingen. Ein langweiliger Stack ist der, den dein Team im Schlaf betreiben kann. Für mich, allein und in kurzen Etappen, ist das Go.

Als Nächstes: warum ich kein Router-Framework verwende.

Mehr in Boring Stack

Teilen