Golang für Cloud-native Entwicklung

Läuft Go bald Java den Rang ab?

| Autor / Redakteur: Filipe Pereira Martins & Anna Kobylinska / Stephan Augsten

GoLand, eine Go-IDE von JetBrains.
GoLand, eine Go-IDE von JetBrains. (Bild: JetBrains)

Verteilte Anwendungsarchitekturen überfordern traditionelle Programmiersprachen. Entwickler von Microservices suchen händeringend nach besseren Alternativen. Kann Go die Platzhirsche ablösen?

Neue Anwendungsarchitekturen und Herangehensweisen wie und Serverless-Entwicklungsframeworks stellen Entwickler vor ganz praktische Herausforderungen der verteilten Anwendungsentwicklung. Althergebrachte Programmiersprachen zeigen sich dieser Aufgabe kaum noch gewachsen.

Mit der quelloffenen Go Programming Language, auch als Golang oder einfach nur Go bekannt, möchte Google ein Allheilmittel ersonnen haben, mit dem Entwickler ihren Microservices in der Cloud eine bisher ungekannte Vitalität verleihen können sollen. Hat für Sprachen wie Java und Python vielleicht doch das letzte Stündlein geschlagen?

„Write once, run anywhere“ vs. „Write quickly, run distributed“

Bei den leichtgewichtigen Anwendungsarchitekturen der Cloud-Ära kommen sich Java-Entwickler schon mal vor, als ob sie mit Kanonen auf Spatzen schießen müssen. Die Stärken der Java Virtual Machine (JVM) kommen bei verteilten Cloud-nativen Microservices kaum zum Tragen. Die Komplexität der Sprache wird Java dabei zum Verhängnis.

Unter Android-Entwicklern lässt die Popularität von Java nicht nach, aber sie beschränkt sich fast ausschließlich auf den Enterprise-Bereich (z.B. das Finanzwesen). Neun von zehn Fortune-500-Unternehmen entwickeln in Java. Die Tatsache, dass Oracles JDK nicht mehr kostenfrei ist, hat die Ausrichtung der Technologie auf Enterprise-Anwendungen nur noch verstärkt.

Bezahlte Support-Verträge können auserlesenen Unternehmenskunden Oracles volle Aufmerksamkeit bescheren. Die übrige Entwicklergemeinde muss sich mehr oder weniger kostenneutral mit der quelloffenen Edition der Java-Laufzeitumgebung OpenJDK begnügen – oder ein Alternative finden.

Kaum aus den Startlöchern und schon auf dem Radar: Der TIOBE-Index für Go.
Kaum aus den Startlöchern und schon auf dem Radar: Der TIOBE-Index für Go. (Bild: TIOBE Software BV)

Die Entwickler Cloud-nativer Anwendungen müssen schnelle Resultate liefern, manchmal auf Biegen und Brechen. Das Erlernen von Java dauert nun aber Jahre; selbst das Entwickeln in Oracles leistungsstarker Universalsprache braucht seine Zeit. Entwickler fragen sich immer öfter, ob das überhaupt noch sei müsste. Ginge es denn nicht irgendwie einfacher? Mit Python vielleicht?

Als kompilierte Sprache kann sich Java die Stärken der Hardware viel eher zu Nutze machen als eine Skriptsprache wie Python. Die hohe, C/C++-ähnliche Performance ist nach wie vor Oracles eindeutige Trumpfkarte. Aber nicht in der Entwicklungsphase, denn Cloud-native Funktionalität entsteht bei Java in mühsamer Handarbeit. Für viele ist der Aufwand einfach zu viel des Guten. Der eine Ansatz ist zu langsam, der andere zu aufwändig.

Vor diesem Hintergrund schickte sich Google an, mit Go eine quelloffene, Cloud-native Entwicklungssprache für verteilte Anwendungsarchitekturen zu lancieren. Das Unternehmen scheint damit Erfolg zu haben. Golang konnte in kürzester Zeit eine beachtliche Schar von Entwicklern gewinnen und taucht in Umfragen seit ca. 2017 unter den relevantesten Sprachen auf.

Stark vertreten und auf Wachstumskurs: 19 Prozent der von JetBrains befragten Entwickler haben sich mit Go bereits auseinandergesetzt; weitere 13 Prozent haben es vor.
Stark vertreten und auf Wachstumskurs: 19 Prozent der von JetBrains befragten Entwickler haben sich mit Go bereits auseinandergesetzt; weitere 13 Prozent haben es vor. (Bild: JetBrains)

In einer Umfrage von JetBrains bekannten sich 18 Prozent der befragten Entwickler im Jahr 2019 zur aktiven Nutzung von Go in den vorangegangenen 12 Monaten. Weitere 13 Prozent haben sich genau das vorgenommen: Die Golang zu lernen und aktiv zu nutzen. Teilnehmer einer Umfrage von HackerRank haben Go zur gefragtesten Sprache gekürt.

Teilnehmer dieser Umfrage von HackerRank unter „praktizierenden“ Entwicklern haben Go zur begehrtesten Sprache gekürt, die sie lernen wollten.
Teilnehmer dieser Umfrage von HackerRank unter „praktizierenden“ Entwicklern haben Go zur begehrtesten Sprache gekürt, die sie lernen wollten. (Bild: Hackerrank)

Golang ist nun mal in aller Munde. Unternehmen wie Upbound, der Spezialist für hybride Clouds mit Plattformen wie Crossplane und Rook im Köcher, schreiben ihre Cloud-Lösungen jetzt nur noch in Go.

Wie gerufen: eine Sprache für Minimalisten

Golang wurde von Grund auf für die Entwicklung verteilter Cloud-nativer Backend-Anwendungen und Frontend-Apps für mobile Endgeräte konzipiert. Darin besteht schon mal das erste Problem: Go ist „anders“. Wer sich bereits in einer anderen High-Level-Sprache wie Java oder C/C++ zu Hause fühlt, muss wirklich umdenken.

Go folgt einem diametral anderen Paradigma als die etablierten Programmiersprachen des Pre-Cloud-Zeitalters. Bestehende Konzepte haben ausgedient, so gibt es beispielsweise weder Klassen noch Konstruktoren oder Destruktoren.

Zur Implementierung einer Methode in Go behelfen sich Entwickler einer Funktion mit einem struct-Empfänger. Um Missverständnissen vorzubeugen: Bei einer Methode in Go handelt es sich de facto um eine Funktion mit dem sogenannten Receiver als Parameter; der Receiver ist wiederum ein Typ, zu dem die jeweilige Methode gehört.

GoLand, eine Go-IDE von JetBrains.
GoLand, eine Go-IDE von JetBrains. (Bild: JetBrains)

Golang bricht demzufolge sowohl mit der Tradition von Klassen und Klassehierarchien (des objektorientierten Models von C++) als auch logischerweise mit der Vererbung von Eigenschaften. Stattdessen hantiert Go mit nicht-hierarchischen Schnittstellen, den so genannten Interfaces.

Golang bricht notgedrungen auch in den anderen Punkten mit „bewährten“ Ansätzen etablierter Programmiersprachen. Die Nebenläufigkeit (auch Parallelität, engl. concurrency), also die Fähigkeit zur gleichzeitigen Handhabung mehrerer Aktivitäten, die miteinander ggf. interagieren können, ist in Go eine fest eingebaute Selbstverständlichkeit. Möglich machen dies die sogenannten Goroutines, Channels und die select-Anweisung (zum Kombinieren der beiden Ersteren).

Bei den Goroutines handelt es sich um eine leichtgewichtige Abstraktion eines Threads. Goroutines können miteinander über die sogenannten Channels bei sehr niedriger Latenz kommunizieren und Daten miteinander austauschen. Während für die Verwaltung gewöhnlicher Threads der OS-Kernel verantwortlich zeichnet, kümmert sich um die Verwaltung der Goroutines im Sinne der Nebenläufigkeit selbst die Go-Runtime – und zwar erst zur Laufzeit.

Die Nebenläufigkeit ist Fluch und Segen zugleich. Sie zwingt die Entwickler, über ihre Anwendungsarchitekturen ganz anders zu denken. Dafür gestaltet sich das Umschalten zwischen Goroutines effizienter, latenzneutraler und ressourcenschonender als zwischen Threads. Das Betriebssystem hat in Goroutines keinen Einblick.

Die Thread-Ablaufplanung in Sprachen wie Java zieht da im Hinblick auf die Performance klar den Kürzeren- Golang-Anwendungen wie AppsFlyer verarbeiten über 70 Milliarden API-Anfragen pro Tag. Das sei das Resultat der Umstellung von Closure auf eine Microservices-Architektur in Golang, so der gleichnamige Anbieter.

Strikte Typisierung ohne implizite Typumwandlungen

Go ist strikt statisch typisiert. Implizite Typumwandlungen wie in Java finden hier nicht statt. Damit das Konzept ohne großen Overhead praxistauglich ist, führt Go die Inferenz nicht-typdeklarierter numerischer Konstanten und nicht-typdeklarierter Variablen automatisch durch. Das sorgt für mehr Typsicherheit, ohne die Entwicklung zu verlangsamen.

Stephan Renatus, Senior Software Development Engineer bei Chef Software, ist von dem pragmatischen Ansatz ganz aus dem Häuschen. „Go ist für uns die erste Wahl“, bestätigt er. Zuvor habe das Unternehmen Erlang/OTP genutzt. Go käme jetzt als eine Allzwecksprache im Backend zum Einsatz. Für datenwissenschaftliche Aufgaben greife das Unternehmen allerdings auf Python zu.

Die Speicherverwaltung von C++ und Java fordert von den Entwicklern einen enormen Wartungsaufwand. Manuelle Speicherverwaltung zählte historisch zu den häufigsten Ursachen für Abstürze der betreffenden Anwendungen. Ein ganzes Minenfeld an milden Bugs tickt in ansonsten sauber programmierten Applikationen vor sich hin wie eine Zeitbombe, um sich nach einem relativ milden Betriebssystemupdate in zahllosen dramatischen Vorfällen von Speicherüberläufen und Adressierungsmissgeschicken zu manifestieren.

Wenn Container und Serverinstanzen zu hunderten oder tausenden bedarfsgerecht initialisiert und terminiert werden sollen, muss die gesamte Umgebung möglichst felsenfeste, vorhersehbare Stabilitätseigenschaften mitbringen. Mit seiner vollautomatischen Speicherbereinigung (Garbage Collection) mit rekordverdächtig niedrigen Latenzen hat Go der mühsamen manuellen Speicherverwaltung ein Ende gesetzt.

In Golang besteht weder die Notwendigkeit noch die Möglichkeit, sich über die verschiedenen technischen Aspekte der Freigabe von Heap-alloziertem bzw. Stack-alloziertem Speicher Gedanken oder gar Sorgen zu machen. Anwendungsentwickler können Arbeitsspeicher hier nicht explizit freigeben.

Go gibt ihnen auch keinerlei Anlass dazu, sich über technische Stolperfallen der Speicherzuweisung und die hypothetischen Feinheiten der malloc-Implementierung auf einem mehr oder weniger virtualisierten System irgendwo in der Cloud Gedanken zu machen. Die Sprache nimmt den Entwicklern zur Laufzeit ihrer Applikationen diese enorme Last von den Schultern.

Fehlerbehandlung in Go

Die Handhabung von Fehlern ist angesichts der verteilten Parallelisierbarkeit in Go von überragender Bedeutung. Doch auch dieses Feature ist minimalistisch ausgelegt. Die meisten Funktionen liefern im Fehlerfalle error-Rückgabewerte zurück. Nur ein katastrophaler, nicht erholungsfähiger Vorfall führt zu einer panic-Laufzeitausnahme.

Bei dem Typ „error“ handelt es sich im Übrigen um eine Schnittstelle. Es lassen sich daran beliebige Datenstrukturen als Werte übergeben und so die Fehler effizienter auswerten. In ihren Fähigkeiten zur Fehlerhandhabung macht Go einen Bruch mit der Tradition der Programmiersprachen, welche lediglich eine Ausnahme auslösen, deren Abarbeitung dann aus Zeitmangel entfällt.

Go-Konventionen fördern die explizite Prüfung der fehlerfreien Ausführung des Codes an jeder Stelle, wo dies von Vorteil erscheint. Mit einem Mechanismus namens Typvermutung (type assertion) lässt sich beispielsweise ein negativer Wert von NegativeSqrtError abfangen und gesondert handhaben, während sich das Verhalten der Applikation in allen anderen Fällen nicht ändert.

Als einen der besonderen Vorzüge von Go führen viele Entwickler die intelligente Erkennung von kritischen Wettlaufsituationen, sprich „race conditions“ an. Diese kritischen Wettläufe zählen zu den besonders schwer auffindbaren Programmierfehlern. Es handelt sich dabei um timingabhängige Bugs, die bei einem unmerklich schnelleren bzw. langsameren Ablauf verschwinden bzw. wieder in Erscheinung treten können.

Bereits das Debugging kann das Timing verändern, so dass der aufzufindende Fehler sich nicht aufspüren lässt, obwohl er später im normalen Betrieb der Anwendung dann doch wieder zum Tragen kommt. Die Problematik der destruktiven Natur der Wettlaufsituationen hat enorme praktische Implikationen. Selbst Google musste zugeben, von kritischen Wettlaufsituationen in dem eigenen Code (zum Beispiel in dem quelloffenen Projekt Chromium) betroffen zu sein.

Der in Go eingebaute Go Race Detector ist in der Lage, solche mysteriösen Fehler aufzudecken. Dank der Nebenläufigkeitsmechanismen (concurrency mechanisms) von Go ist es zwar deutlich leichter, sauberen nebenläufigen Code zu schreiben. Nichtsdestotrotz sind kritische Wettläufe dennoch möglich; dieser Art von Programmierfehlern können Entwickler auch in Go lediglich mit sorgfältiger Programmpflege, ausgiebigen Tests und passenden Werkzeugen wie dem Go Race Detector beikommen.

Die mit Go bereitgestellte Toolchain, Googles offizielle Sammlung von Programmierwerkzeugen für die Go-Sprache, ist erstaunlich umfassend: Ein Test-Framework, das in die Sprache selbst integriert ist und auch Berichte zur Codeabdeckung erstellen kann, weiterhin ein Linter und viele andere Tools für statische Analysen.

Der in Go integrierte Quellcode-Formatierer (gofmt) bringt einen wahren Sprung in puncto Produktivität mit sich. Offenbar hatte Google eingesehen, dass die Arbeitszeit eines Entwicklers zu wertvoll ist, um sie mit der manuellen Formatierung von Code zu vergeuden. Gofmt optimiert deshalb die Lesbarkeit des Quellcodes.

Golang-Code kompiliert sich zur Maschinensprache. Go-Builds einer gewöhnlichen Größe kompilieren sich ohne jegliche Wartezeiten und auch sehr umfangreiche Projekte brauchen lediglich wenige Sekunden bis zur Fertigstellung der Binäranwendung. Das effiziente Package-Management zählt zu den Highlights der Sprache. Die resultierende Binärdatei beinhaltet dann auch die Abhängigkeiten.

Spitzenperformance spricht sich schnell herum

Go kombiniert die Entwicklungsgeschwindigkeit von dynamischen Sprachen wie Python oder Ruby mit der Leistungsfähigkeit und der Sicherheit von kompilierten Sprachen wie C, C++ oder Java. Die Performance von Go macht inzwischen von sich reden.

Mark Markaryan, Principal Software Engineer bei Drift, empfindet Golang-Code als „wartungsfreundlich, testbar, leichtgewichtig und leistungsfähig“. Das Unternehmen prototypisiert seine Web-Services in Elixir, modelliert seine Daten in Python und entwickelt seine Microservices in Go. „Go ist für uns sehr nützlich zum Entwickeln von Microservices“, bestätigt auch Loren Anderson, Lead Software Developer bei iTrellis, einem Systemintegrator aus Seattle im U.S.-Bundesstaat Washington.

GraalVM: Oracles Gegenoffensive?

Der Siegeszug von Java im Cloud-Backend scheint neuerdings zu stottern. Diese Erkenntnis bestätigt u.a. der aktuelle TIOBE-Programming-Community-Index. Oracle, einst unerschütterlich, macht einen verunsicherten Eindruck. Seit dem 17. September 2019 steht Java-Entwicklern die dreizehnte Generation von Java zur Verfügung. Die verkürzten Release-Zyklen konnten den Trend jedoch bisher nicht umkehren.

Der TIOBE-Index führender Programmiersprachen zwischen Juni 2001 und September 2019: Bei Java und C/C++ scheint sich langsam Ernüchterung einzustellen; Python wächst tapfer in seiner Nische der Datenwissenschaften weiter und bei PHP ist die Luft raus.
Der TIOBE-Index führender Programmiersprachen zwischen Juni 2001 und September 2019: Bei Java und C/C++ scheint sich langsam Ernüchterung einzustellen; Python wächst tapfer in seiner Nische der Datenwissenschaften weiter und bei PHP ist die Luft raus. (Bild: TIOBE Software BV)

Oracle hat die Bedrohung durch die Go-Gemeinde offenbar erkannt und auch schon zur Gegenoffensive geblasen. Mit einer Universal-VM, getauft auf den verheißungsvollen Namen GraalVM, sollen sich viele verschiedene Sprachen in einer gemeinsamen Laufzeitumgebung miteinander „verschalten“ lassen.

GraalVM ist eine quelloffene, „polyglotte“ Virtual Machine, die sich auf JavaScript, Python, Ruby, C, und C++ und auch JVM-Sprachen wie Java, Kotlin und Scala versteht. Ähnlich wie Golang soll sie eine kurze Initialisierungszeit gewährleisten und einen kleinen Memory-Fußabdruck aufweisen.

GraalVM könnte jedoch anders als Golang aus dem Java-Ökosystem einen Nutzen ziehen, und sei es „nur“, um Java-Objekte an Python zu übergeben. Als besonderen Leckerbissen verfügt die GraalVM über die Fähigkeit, Ahead-of-Time-Compilation für Java-Code durchzuführen. Das Ende der Fahnenstange bei GraalVM ist bisher Java 8, eine Altlast.

Im Oktober 2019 möchte Oracle mit GraalVM 19.3 dann aber auch Java 11 unterstützen. Bei Java 11 handelt es sich bereits um eine LTS-Release (Long Term Support) handelt. Der Premier-Support gilt bis zum September 2023 und der Extended-Support sogar bis zum September 2026 als gesichert.

Fazit

Go/Golang könnte wohl kaum zu einem besseren Zeitpunkt entstanden sein. Die Cloud-native Entwicklergemeinde ist aufnahmebereit gegenüber tiefgreifenden Veränderungen. Denn verteilte Anwendungsarchitekturen fordern nun mal ein radikales Umdenken. Die Programmiersprache adressiert die Schwächen etablierter Entwicklungssprachen im Kontext von Cloud-nativen Deployments.

Oracles GraalVM ist aber auch nicht zu unterschätzen. Das Rennen zwischen Golang und GraalVM 11.3 verspricht, interessant zu werden. Weder Google noch Oracle kann es sich leisten, einen Gang herunterzuschalten. Die wahren Gewinner dürften letztendlich die Entwickler sein.

Kommentare werden geladen....

Kommentar zu diesem Artikel

Der Kommentar wird durch einen Redakteur geprüft und in Kürze freigeschaltet.

Anonym mitdiskutieren oder einloggen Anmelden

Avatar
Zur Wahrung unserer Interessen speichern wir zusätzlich zu den o.g. Informationen die IP-Adresse. Dies dient ausschließlich dem Zweck, dass Sie als Urheber des Kommentars identifiziert werden können. Rechtliche Grundlage ist die Wahrung berechtigter Interessen gem. Art 6 Abs 1 lit. f) DSGVO.
  1. Avatar
    Avatar
    Bearbeitet von am
    Bearbeitet von am
    1. Avatar
      Avatar
      Bearbeitet von am
      Bearbeitet von am

Kommentare werden geladen....

Kommentar melden

Melden Sie diesen Kommentar, wenn dieser nicht den Richtlinien entspricht.

Kommentar Freigeben

Der untenstehende Text wird an den Kommentator gesendet, falls dieser eine Email-hinterlegt hat.

Freigabe entfernen

Der untenstehende Text wird an den Kommentator gesendet, falls dieser eine Email-hinterlegt hat.

copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Kontaktieren Sie uns über: support.vogel.de/ (ID: 46154660 / Programmiersprachen)