Go - Warum der Hype? - Erfahrungen & Stuff about Go
Go, eine Sprache von Google. Der Hype um die Programmiersprache scheint ungebrochen. Vor allem im Cloud Native-Umfeld findet sich Go an jeder Ecke, oder besser gesagt in jedem Container. Ich will heute einen kleinen Einblick geben, warum der Hype durchaus berechtigt ist und es sich unter allen Umständen lohnt mindestens einen verstohlenen Blick auf das ganze Ökosystem Go zu werfen.
Der wichtigste Grund
ist wohl das Maskottchen für GOlang - das Gopher:
Na gut, das ist nicht der wichtigste Grund, aber vom Gopher gibt es die verschiedensten Variationen und Abwandlungen für Projekte rund um Golang.
All in One
Um Go entwickeln zu können braucht man lediglich ein Archiv das man sich auf der Official Page herunterladen kann. Nach der Installation von Go, die sich auf *nix-Systemen in einer Zeile vornehmen lässt, kann man schon loslegen.
Alles was das Herz begehrt ist bereits integriert:
- go build - (Cross-)Compilation
- go run - Compile & Run
- go get - Dependencies herunterladen und installieren
- go fmt - Code nach Konvention formatieren
- go test - Tests ausführen (mit Coverage Reports etc.)
- go vet - Linting/Error prevention
Die Liste ist an der Stelle noch viel länger, das sind nur einige der wichtigsten Tools. Alles mit der Grundinstallation von Go!
Ich hab nun schon einige Programmiersprachen gelernt und damit Projekte umgesetzt, an Go reichte bis jetzt allerdings kein Ökosystem. Ohne Third-Party Extensions, IDE usw. kommt man hier schon bis in Production! Alle Tools sind durch die direkte Integration in Go entsprechend stabil und funktionieren tadellos mit der aktuell installierten Go-Version.
Portability
Go kompiliert zu nativen Machine-Code. Nachdem der Trend immer mehr in Zwischensprachen wie Byte-Code usw. ging, geht Go hier bewusst den Weg der nativen Kompilierung. Das tut der Portabilität jedoch keinen Abbruch. So lässt sich eine CommandLine-App mit Boardmitteln für alle gängigen Betriebssysteme und Plattformen bauen.
Im Hinblick auf das Cloud-Umfeld bietet das den Charme, dass ein Container sehr klein ist. In Kombination mit den Multi-Stage Builds lassen sich so extrem schlanke Images erstellen, die vollfunktionsfähig und extrem leicht skalier- und wartbar sind. Wahrscheinlich ist das auch einer der Hauptgründe warum Go gerade im Cloud Native-Umfeld so viel Zuspruch erfährt. Aber auch für CommandLine-Anwendungen bietet das natürlich eine Möglichkeit eine stabile CLI in einer einzigen Binary auszuliefern.
Moderne Standard-Library
Während sich die meisten Sprachen in ihrer Standard-Bibliothek meist nur um sehr primitve Grundfunktionen bemühen, geht Go hier den Weg standardmäßig production-ready HTTP-Server und JSON-Verarbeitung zu integrieren. Das macht es ziemlich einfach ohne eine einzige Third-Party-Lib einen funktionierenden Micro-Service zu schreiben!
Auch für CommandLines hält Go ein ziemlich praktikables Set an Tools und Möglichkeiten um Entwicklern die Entwicklung zu erleichtern. Das geht vom Parsen von Argumenten bis hin zum Fehler-Handling und dem richtigen Verarbeiten von OS-Signalen.
Testing built-in
Für alle Programmiersprachen die ich bisher erlernt habe musste ein Framework herhalten wenn es in Richtung Testing ging. Die Vielzahl an Möglichkeiten und Patterns macht es hier für neue Projekt-Member sehr schwer sich zu recht zu finden, wenn dieser vorher mit anderen Testing-Suites gearbeitet hat.
Bei Go wurde bereits ein ziemlich primitives, aber mächtiges Testing mit integriert. Hierbei wird die jeweilige Code-File direkt mit einem Counter-Part versehen, die entsprechend alle Tests enthält. Was am Anfang wie der Albtraum für jeden PHP und Java-Entwickler klingt, stellt sich mit der Zeit als komfortabel heraus. Die enge Verbindung zwischen Test und Code macht es besonders bei der Entwicklung über das Terminal einfach hin und her zu wechseln und sich nicht erst die Tests heraussuchen zu müssen.
Wenn es um die Auswertung der Tests geht bietet Go hier von dem klassischen Protokoll der Testfälle auch einen Coverage-Report in HTML-Form an, der sich direkt nach der Ausführung im Browser ausführen lässt und so schnell einen Überblick liefert. An der Stelle ist es auch möglich die Coverage etc. noch selbst auszuwerten und weiterzuverarbeiten. Hier sind also alle Möglichkeiten offen.
Simples Dependency Management
Dependencies sind in Go ziemlich leicht zu erkennen. Der Import-Pfad ist die umgekehrte Webadresse für ein Git-Repository, gefolgt von dem entsprechenden Pfad. Das macht es ziemlich einfach auch in den Source-Code zu blicken oder herauszufinden wo die Dependencies genau herkommen. Die Dependencies werden hierbei entweder aus einem globalen Pfad, dem sogenannten GOPATH geladen. Alternativ gibt es seit Go 1.11 die sogenannten Go Modules, hierbei wird im Projekt in der Datei go.mod definiert, welche Go-Version genutzt werden sollte und wo sich die Dependencies finden und in welcher Version. Das sorgt für eine stabilere Verwaltung von Dependencies. Diese werden standardmäßig auch im GOPATH installiert, lassen sich aber auch auf einen lokalen Ordner im Workspace umkonfigurieren. Per Konvention ist dieser meistens vendor, ähnlich wie bei Composer im PHP-Umfeld.
Alles in allem erinnert das Dependency-Management sehr an das von Node.js mit npm, mit dem großen Unterschied das Go hier deutlich dezentraler arbeiten kann. Meiner Meinung nach wurde hier das beste aus allen Dependency-Management-Tools kombiniert. Es ist simpel, mächtig aber jederzeit transparent nachvollziehbar. So hatte ich noch nie Probleme mit Abhängigkeiten oder Inkompabilitäten im Go-Umfeld.
Performance
Go ist, auch durch seine native Kompilierung geschuldet, sehr schnell und dabei sehr effizient. So lassen sich mit Go hochskalierbare Services und sehr resourcenschonende CommandLine-Tools und Systemdienste erstellen. Der eingesetzte Garbage-Collector arbeitet hierbei mit verschiedenen Tricks und sorgt für ein exzellentes Memory-Management.
Hierbei hat der Entwickler immer die Wahl ob er mit pass-by-reference oder pass-by-value arbeiten will, ohne das er sich um die Gargabe-Collection kümmern muss. Das führt zu einer sehr hohen Flexibilität bei geringen Problemen durch Memory Leaks, da diese deutlich schwieriger zu verursachen sind.
Parallelität
Die sogenannten Go-Routinen bieten effizienten Coroutinen an um auf schwergewichtige Threads verzichten zu können. Diese können hierbei über Kanäle mit einander kommunizieren und so effizient Daten austauschen und parallele Prozesse steuern.
Hierbei lässt sich eine beliebige Methode mit dem Schlüsselwort go in eine solche Goroutine verwalten. Das ermöglicht grundsätzlich jeden Code parallelisieren zu können, auch wenn er von einer Quelle stammt, deren Source ich nicht modifzieren kann. Das bietet eine extreme Flexiblität und macht dabei noch eine sehr gute Figur.
Minimalistische Syntax
Go verzichtet auf viele den Parsern geschuldete Relikte, wie Strichpunkte zum Abschliessen einer Anweisung oder der Verwendung von Klammern bei If-Abfragen und Schleifen. Das sorgt für einen schlanken und übersichtlichen Code der sich extrem gut lesen lässt.
Hierbei werden Zeilenumbrüche sehr strikt verarbeitet, was dazu führt dass, wie bei Python, viele Unleserlichkeiten gleich vor der Ausführbarkeit des Programmes vermieden werden.
In den allermeisten Fällen muss bei Go kein Typ für Variablen angegeben werden, hierbei erkennt der Compiler anhand der Initialisierung den entsprechenden Typen, im Gegensatz zu dynamisch typisierten Sprachen ist so ein Typ vorhanden, ohne das er explizit angegeben werden muss. Das Ganze ist daher am Besten zu vergleichen mit dem "Typenplatzhalter" var in C#.
Alles in Allem sorgt diese minimalistische Syntax für einen leicht lesbaren Code, ohne unnötigen Balast, was vorallem Code-Reviews und das Lesen fremden Source erheblich vereinfacht und zu einer sehr angenehmen Tätigkeit macht.
Community
Die Go-Community besteht aktuell zu einem sehr sehr großen Teil aus Enthusiasten die mit Go Spaß haben. Man könnte sagen das stellt einen sehr harten Kontrast zu der Java-Community dar, die mehr vom Enterprise geprägt ist. Dadurch dass Go sich langsam aber sicher in die Enterprise-Richtung entwicklen wird, bzw. dort immer mehr Einsatzgebiete erfährt bleibt abzuwarten wie sich die Community dahingehend entwickelt.
Ja, Google. Eine große Firma hinter einer Sprache oder Technologie, nicht zuletzt Google, ist meist ein Garant für den Erfolg.
Go wurde für die extremen Anforderungen von Google zu mehr Skalierbarkeit, Performance und Parallelität bei einer Vielzahl von Entwicklern entwickelt. Das macht sich an sehr vielen Stellen von Go bemerkbar.
Thats it!
Wie du vielleicht bemerkt hast, bin ich ein kleiner Go-Fanboy. Die Sprache enthält fast alles was eine Programmiersprache meiner Meinung nach haben muss. An sich ist Go anders zu erlernen wie jede andere Sprache die ich bisher erlernt habe.
Es gibt durchaus einige Parallelen zwischen anderen Sprachen und Go. Doch der Mindset bei der Entwicklung mit Go ist ein komplett anderer. Gerade wenn man von einer sehr abstrakten Sprache wie Java her kommt wirkt am Anfang alles sehr primitiv. Man kann aber ziemlich schnell mit Go produktiv werden und großes Schaffen.
Was du nicht erwarten darfst, ist mit Go einen Monolithen zu bauen, das mag funktionieren aber es wird sich nicht richtig anfühlen und dich einholen. Go hat andere Stärken, die ihr Potenzial nur dann nutzen wenn man es für das richtige benutzt. Gemäß dem Motto
Use the right tool for the job!
Ein Blick auf Go als solches lohnt sich alle Mal, da immer mehr neue Projekte in Go geschrieben sind, ein nützlicher Skill also wenn man sich die Interna eines CLI-Tools, dem LoadBalancer uvm. genauer ansehen und verstehen will.