Transkript

Go

Moderne Sprache mit altbackenen Konzepten

Lucas hat sich die beiden Gründer der Go-Usergroup Rhein-Ruhr und versierten Go-Kenner Christoph und Philipp geschnappt und sie gründlich zu den Besonderheiten dieser Programmiersprache ausgefragt. Warum eigentlich eine neue Sprache und ist sie alltagstauglich? Außerdem: Warum Go die Sprache der Cloud ist.

Zurück zur Episode

Transkript

Lucas Dohmen: Hallo und herzlich Willkommen zu einer neuen Folge des INNOQ Podcast. Heute sprechen wir über ‚Go‘ und dafür habe ich mir direkt zwei nette Kollegen eingeladen: Den Philipp und den Christoph. Ja, erstmal: Wer seid ihr? Und was macht ihr hier bei INNOQ? Philipp, stell dich doch mal kurz vor.

Philipp Haußleiter: Hallo, mein Name ist Philipp Haußleiter. Ich bin bei der INNOQ schon eine ganze Weile. Bin gestartet mit Java, habe zwischendurch auch immer mal Front-End Sachen gemacht und seit einigen Jahren beschäftige ich mich vorwiegend auch mit der Entwicklung in Go. Mache da zeitweise auch infrastrukturnahe Systeme und möchte heute erzählen, wieso das so ist.

Lucas Dohmen: Cool, alles klar! Und du Christoph?

Christoph Iserlohn: Ja, mein Name ist Christoph Iserlohn. Ich bin auch schon eine ganze Zeit bei der INNOQ. Nicht ganz so lange wie der Philipp, aber auch schon jetzt im neunten Jahr. Ich beschäftige mich schon immer mit verteilten Systemen, wenn man das heute noch so nennen will. Heute sind es halt irgendwie Microservice Landschaften, aber früher nannte man das ‚verteilte Systeme‘. Und mit den Themen Security, da mache ich auch den Security Podcast von INNOQ zusammen mit dem Kollegen Simon Kölsch. Und ich bin so ein kleiner Programmiersprachen Nerd, also ich habe a) schon in meinen Projekten ganz viele Programmiersprachen benutzten können, manchmal auch müssen und mache das so auch in meiner Freizeit. Also da kenne ich eine ganze Menge und so bin ich eigentlich auch zu Go gekommen.

Lucas Dohmen: Ja, cool. Dann klingt das ja so als würden wir hier geballtes Go-Wissen präsentiert bekommen von zwei alten INNOQ Hasen. Dann fangen wir doch erstmal so ein bisschen mit dem historischen an. Wo kommt denn diese Sprache her? Wer hat das gebaut? Und wieso? Es gibt ja schon so viele Programmiersprachen, warum baut man noch eine?

Christoph Iserlohn: Also Go kommt von Google und der Legende nach haben sich das die Erfinder von Go überlegt, während sie mal wieder darauf warten mussten, dass irgendein riesiges C++ Programm kompiliert hat, dabei. Und haben dann an so einen White Board halt aufgeschrieben, was denn so Sachen sind, wie sie eine vernünftige Systemprogrammiersprache machen wollen. Also eine, die ein Ersatz für C++ oder C sein könnte. Und das war im Jahr 2009 und… beziehungsweise vielleicht auch schon 2008, 2009 ist das erste Mal erschienen öffentlich und seit 2012 gibt es Go 1.0, also die stabile Version, wo jetzt auch so eine versprechende Rückwärtskompatibilität gegeben ist, darauf kommen wir gleich vielleicht nochmal zurück. Ja und da ist das entstanden. Und das ist so ein bisschen C-ähnlich geworden, das hat auch den Grund, weil da so Leute wie Ken Thompson mitgearbeitet haben, die schon früher in Unix gearbeitet haben und die haben dann auch ihre…, sozusagen ihre Präferenzen da mit eingebaut, sehr C ähnlich.

Lucas Dohmen: Okay, du hast jetzt da in deiner Einführung erzählt, dass ist eine Sprache von Google. Wie stark ist denn die Bindung an Google. Ist das eine Sprache, die jetzt auch von der Community getragen wird oder ist das wirklich so eine Firmensprache? Wie schätzt du das ein?

Christoph Iserlohn: Also das ist ein Open Source Projekt unter der BSD-Lizenz, das heißt das kann jeder erstmal so verwenden, wie er will. Es gibt auch eine sehr große Community, das können wir vielleicht auch nochmal im Detail später besprechen, die da auch sehr viel mitwirkt an der Entwicklung. Aber Go wird trotzdem noch hauptsächlich von Google vorangetrieben, weil viele, die daran arbeiten halt in Vollzeit bei Google davon bezahlt werden, während die Community, wenn man das so hobbymäßig macht, gar nicht so viel Zeit investieren können.

Lucas Dohmen: Alles klar. Gut, was ist denn neu bei Go? Was macht denn Go toll? Warum sollte ich mir das anschauen?

Christoph Iserlohn: Go hat eigentlich ganz wenig Neuigkeiten. Man könnte auch sagen, eigentlich hat es keine Neuigkeiten gegenüber den anderen Programmiersprachen, sondern das war auch nicht das Designziel. Sondern das war mehr so, dass man eher Sachen weglässt, die man nicht gebrauchen kann. Sondern man hat das sehr pragmatisch aufgefasst und sagt: Okay, was brauchen wir denn um in großen Teams mit vielen Entwicklern und einer großen Code-Basis was entwickeln zu können? Und da hat man als erstes festgestellt: Okay, bei großen Code-Basen und vielen Leuten, die vielleicht auch dann viel unbekannten Code lesen müssen, sollten wir die Sprache relativ einfach gestalten. Und dann kommt es halt so, dass man solche Sachen, die man heute vielleicht als selbstverständlich sehen würde bei einer neuen Programmiersprache, dass man sowas wie Exception zum Beispiel bei der Fehlerbehandlung weggelassen hat, sondern dass das einfach so wie bei C üblicherweise über einen einfachen return value geprüft wird, ob ein Fehler im Programm aufgetreten ist. Also viel Neues gibt es nicht. Das Einzige, was man erwähnen kann, was sie direkt gemacht haben, ist, dass man Concurrency Konstrukte direkt mit in die Sprache aufgenommen hat, weil zu dem Zeitpunkt, so um 2010 war ja schon klar, dass die meiste Rechenleistungs-Steigerung nicht mehr darüber kommt, dass wir jetzt bei 50 Gigahertz Prozessoren sind, sondern dass wir halt x Cores haben und die müssen irgendwie ausgenutzt werden. Und das hat man halt direkt berücksichtigt und da hat man dann Go Routine und Channels, können wir auch gleich nochmal im Detail erklären, mit aufgenommen.

Lucas Dohmen: Okay, aber du hast schon erwähnt, so ein bisschen Sachen wurde weggelassen. Du hast jetzt erwähnt exceptions und Generics. Was fällt dir noch so ein, was… oder auch dir Philipp, was sonst weggelassen wurde? Was vielleicht sonst üblicherweise in einer Sprache drin ist?

Philipp Haußleiter: Also ein großer Punkt, den auch viele Leute dann immer so ein bisschen abschreckend finden, ist halt, dass komplett auf Klassen und eigentlich auch große Vererbungshierarchien verzichtet worden ist. Also das ist halt das, was man klassischerweise als Java Entwickler lernt: Alles ist irgendein Objekt, du hast eine Klasse und dann hast du am besten noch eine ganze Vererbungshierarchie von Klassen. Und in Go ist das Ganze halt ein bisschen eingedampft worden. Das heißt man kann schon objektorientiert programmieren, aber es funktioniert halt anders als man das halt von Java gewohnt ist.

Christoph Iserlohn: Ja, dazu muss man sagen, dass die Objektorientierung da drin ist, aber halt anders als die Klassen…, also eine typische klassenbasierte mit Vererbung gebaute Objektorientierung. Aber, das wird jetzt den Java Programmierer erschrecken, aber vielleicht den JavaScript Programmierer nicht so. Weil der kann zum Beispiel mit prototypbasierter OO, auch schon ein anderes Model, das würde ich gar nicht so herausstreichen. Lucas, du hast gerade gesagt, Generics sind raus und hast mir das unterstellt, dass ich das gesagt hätte, habe ich aber nicht. Aber da hast du Recht, das ist ein großer Kritikpunkt, dass man die rausgenommen hat. Aber das macht sich auch an Kleinigkeiten bemerkbar so, es gibt zum Beispiel nur eine einzige Schleifenkonstrukt mit For und es gibt keine While Schleife oder Do-While Schleife oder sonst… Repeat, sondern es gibt For, die dann in mehreren Varianten kann ich die aufrufen, so dass ich so den Komfort habe wie so ein For…in, dass ich über irgendetwas iteriere oder einfache For Schleife mit Zähler kann ich damit machen oder auch eine endlos Schleife, aber dafür hat man halt von der Syntax zum Beispiel dann nicht drei verschiedene Konstrukte gemacht. Also da hat man es auch sehr einfach gehalten.

Philipp Haußleiter: Generell war es halt auch so gedacht, dass die Syntax halt sehr klein gehalten wurde, weil halt auch eines der Ziele war, dass man Go relativ schnell lernt. Also nicht wirklich beherrschen, aber dass man alle Sprach Konstrukte in einem kurzen Zeitraum dann auch beherrschen kann.

Christoph Iserlohn: Also man sieht das typischerweise daran auch, dass das viele weniger Schlüsselwörter hat, also zum Beispiel C++ und das sollte ja auch ein Ersatz dafür sein. Und hat glaube ich nur ein Drittel oder ein Viertel der Anzahl der Schlüsselwörter, die zum Beispiel C++ besitzt.

Lucas Dohmen: Ja, ich meine C+ ist natürlich auch relativ bekannt dafür relativ umfangreich zu sein, sage ich jetzt mal vorsichtig. Aber wo wir gerade bei diesen Vergleichen sind: Wie ist das denn? Ist das eine Programmiersprache, bei der ich das Memory irgendwie von Hand managen muss, wie jetzt bei C mit Pointer und was weiß ich was? Oder gibt es einen Garbage Collector? Wie ist es da positioniert?

Christoph Iserlohn: Also es ist eine Sprache mit Garbage Collector. Ich muss mich nicht darum kümmern, wie ich jetzt Speicher alloziere und den auch wieder freigebe, weil das ja ein großes Problem bei C und C++ in Sachen Security ist, weil das ungefähr 70% aller Sicherheitslücken in diesem Programm zu verantworten hat. Andererseits habe ich aber trotzdem noch Zeiger, also da merkt man noch so ein bisschen die Unix Herkunft und die C Herkunft. Es gibt Zeiger, aber eine Einschränkung gibt es: Es gibt keine Zeigerarithmetik und das heißt da haben wir noch eine Quelle von vielen Fehlern ausgeschlossen. Zeigerarithmetik in C führt halt auch oft zu Fehlern. Macht es manchmal komfortabel, aber an der Stelle wurde einfach drauf verzichtet. Aber so kann man dann ein bisschen die Speichersteuerung übernehmen, weil ich weiß dann zum Beispiel… Oder damit er steuern kann, ob das auf dem Heap alloziert wird oder auf dem Stack alloziert wird.

Lucas Dohmen: Okay, aber… das heißt aber ich muss nicht jetzt irgendwie ein free Memory oder irgend sowas aufrufen, um irgendetwas aus dem Speicher rauszunehmen und so weiter.

Christoph Iserlohn: Das nicht, das macht der Garbage Collector automatisch, dass der halt periodisch aufräumt. Trotzdem sind Zeiger etwas, wo zum Beispiel Java-Programmierer oft…, also die vorher Java gemacht haben und die dann umsteigen, ein Problem mit haben, weil sie das noch nie so unbedingt gesehen haben oder vielleicht mal irgendwann in der Uni, wo sie mal einen C-Kurs über ein halbes Jahr hatten, das macht denen dann doch schon Probleme damit umzugehen. Während die Leute, die von C und C++ kommen, das eigentlich als selbstverständlich ansehen, dass man natürlich irgendwelche Zeiger, also Pointer hat und damit arbeitet.

Lucas Dohmen: Und so im Bereich von Typsystemen, ist das sowas, womit man dynamische Typisierung hat? Oder wird das viel mit type inference irgendwie, dass man gar nichts hinschreiben muss, aber der findet die Typen selber raus? Wie ist es da so in Go?

Philipp Haußleiter: Also Go hat ein statisch getyptes System. Das heißt man kann auch durch Typen konvertieren, die ist halt eingebaut und die Art und Weise welche Werte man einer Variabel zuweist den Typ bestimmen. Aber generell ist es so, dass man sich schon mehr Gedanken machen muss, welche Werte man in Variablen abspeichern will. Das ist halt nicht so wie bei Ruby oder JavaScript, was halt dynamisch dann auch geändert werden kann.

Lucas Dohmen: Alles klar. Und wird dabei irgendetwas inferriert oder muss ich da wirklich an jedem einzelnen Call immer… bei jeder einzelnen Zuweisung immer dranschreiben welcher Typ das ist. Wie ist das da in der Benutzung?

Christoph Iserlohn: Also es gibt eine lokale type inference, das ist, wenn ich jetzt eine Variable habe und dann auf der rechten Seite eine Zuweisung und dadurch der Typ sich automatisch… Also der Typ inferriert werden kann vom Compiler, dann macht der das auch. Also ich kann jetzt A Doppelpunkt, Gleich und dann in Anführungszeichen “string“ dahinschreiben, das funktioniert. Das ist so wie das var Keyword in Java oder auto in C++ zum Beispiel, aber die ist bei weitem halt nicht so mächtig wie bei Haskell oder so. Von daher ist es auch schwierig, da es ja keine Generics gibt, dann irgendwie auf Funktionslevel oder ähnlichen, irgendeine type inference zu machen. Das gibt es halt dann dadurch sowieso nicht, da ich keine Generics habe.

Lucas Dohmen: Alles klar. Das heißt also, meine Funktionssignaturen, da stehen auf jeden Fall schonmal immer die Typen dran?

Christoph Iserlohn: An der Funktionssignatur steht immer der Typ dran. Also ich habe immer die Parameter, die ich übergebe und den Rückgabewert, die muss ich immer fest typisieren.

Philipp Haußleiter: Es gibt noch eine Besonderheit. Und zwar gibt es bei Go ein empty interface, also speziell, wenn man so Sachen macht wie: Ich möchte jetzt einen JSON einlesen. Dann wäre es ja irgendwie hinderlich, wenn man dann jedes Mal quasi gleich festhalten muss, welcher Typ dann quasi mein Value hat und dementsprechend gibt es da so ein Kürzel, dass man das Ganze gegen ein Interface einliest. Also das ist ein spezielles Go-Konstrukt und dann hinterher erst auf einen spezifischen Typ quasi casted.

Lucas Dohmen: Alles klar. Und wie ist das, ihr habt ja gesagt: Go ist so eine Sprache, die viele Sachen weggelassen hat. Und ihr habt ja jetzt schon alle Programmiersprachen davor gemacht. Gibt es etwas was ihr vermisst aus Sprachen, die ihr sonst gemacht habe? Also wo ihr sagt: Ah, schade dass sie das weggelassen haben, das hätte ich gerne in der Sprache.

Christoph Iserlohn: Also ich muss sagen, dass man Generics weggelassen hat, das ist das Einzige was ich vermisse. Also die sollen ja auch in Zukunft kommen mal, können wir auch später drüber reden. Aber das ist etwas, was ich wirklich vermisse, was… Also da macht die Sprache so ein bisschen das durch was Java durchgemacht hat, wo es ja auch bis Version 1.5 keine Generics gab. Da hätte man sich vielleicht ein bisschen mehr an den anderen Sprachen orientieren können, die es schon gibt. Die Begründung war, dass man… nicht, dass man sagt: Generics sind schlecht. Sondern man hat keine Ahnung wie man die vernünftig implementieren kann, deshalb hat man sie erstmal weggelassen, also wie man es vernünftig macht. Naja, ansonsten finde ich das ganz gut, dass relativ viel weggelassen wird. Ich kann Go Programme, die ich noch nicht gesehen habe, relativ leicht lesen, weil die durch das Weglassen halt auch immer gleich aussehen. Manche sagen das sieht ganz schlimm aus, weil man da solche If/Else Orgien hat, beziehungsweise gar kein Else, sondern es wird immer geprüft: If, irgendein Fehler und dann gibt es eine Return, dann wird diese Funktion verlassen mit einem Fehlerwert und das ist jetzt ästhetisch vielleicht nicht das schönste, aber man kann es halt einfach super lesen durch die Gleichförmigkeit und die wenigen Konstrukte. Und auf der anderen Seite, wir haben jetzt viel über das Weglassen gesprochen, bei der Standardbibliothek hingegen hat man viele Sachen drin, die man in anderen Standardbibliotheken nicht so findet. Also es gibt eine relativ gute Template Engine direkt drinnen. Das ist aus meiner Erfahrung in Projekten immer ein Problem, welche Template Engine nehmen wir denn jetzt? Es gibt so viele mit Vor- und Nachteilen. Da gibt es halt eine und es gibt selten einen Grund die zu verlassen. Oder was mich in Sachen Security interessiert, da gibt es noch eine sehr gute Kryptolibrary drin, das haben auch die wenigsten Programmiersprachen. Die meisten Programmiersprachen linken da dafür gegen OpenSSL und haben da ein ganz schlechtes API drauf, weil OpenSSL einfach auch, aus meiner Sicht, ein schlechtes API anbietet. Und da gibt es halt eine sehr gute Kryptolibrary, die relativ sicher ist… Was heißt relativ sicher? Die einen guten Ruf hat unter den Security Leuten in Sachen Sicherheit und die auch extrem schnell ist. Man hat da, gerade Cloudflare, hat da viel investiert drin. Da merkt man auch wieder, das ist halt Open Source und die haben manche Sachen, also ihre Sachen halt direkt am Internet hängen, die in Go geschrieben sind und da müssen sie halt auch ordentlich fluppen und da haben die einige Optimierungen da eingebaut. Und wenn man normal AES 128 nimmt bei TLS, dann ist Go schneller als der nginx in dem Fall. Ist jetzt ein spezieller Benchmark, aber da weiß man was die da reininvestiert haben, damit dieses ganze Krypto-Zeug halt auch fluppt. Und von daher ist es etwas, was ich sehr schätze.

Lucas Dohmen: Cool. Und du Philipp? Was… Wie siehst du das?

Philipp Haußleiter: Also letztendlich einer der Hauptkritikpunkte, wenn das überhaupt einer ist, sind halt die Möglichkeiten ein Programm zu Debuggen. Also gerade auch wenn man ein relativ großes Programm hat, wo man viele Datenflüsse hat, ist man da, wenn man den Java Debugger gewohnt ist, halt auch schon so ein bisschen verwöhnt. Und darum muss man halt sagen, da muss man bei Go halt mehr Wissen wie das Binary selbst funktioniert. So Stacktraces, wie man sie vielleicht in Java kennt, kriegt man halt auch nicht geliefert. Also das war etwas, wo man gerade auch bei der Fehleranalyse ein bisschen Übung braucht. Um das Ganze nochmal mit guten Dingen auszugleichen: Also letztendlich finde ich halt auch einen großen Vorteil, dass es in Go eine Art Auto-Formater gibt. Also jeden Quelltext eines Go-Programmes den du öffnest, ist halt gleichmäßig formatiert, weil es halt zur compile-Zeit halt so definiert ist. Also dieses alte Tabs vs Spaces, wie viele Einrückungen und so, wird einem halt von der Sprache abgenommen. Und was mir halt auch manchmal gefehlt hat, gerade auch am Anfang, war, dass es halt auch einen relativ freigestellt wird, wie man sein eigenes Projekt strukturiert. Also welche Sourcecode Bestandteile wo in welchen Verzeichnisbau liegen. Es gibt mittlerweile Ansätze wo einfach so Template Projekte zur Verfügung gestellt werden, aber wenn man gerade neu anfängt und irgendwie jetzt ein Modul baut oder eine Webanwendung oder, was bei Go häufiger vorkommt, eine Repository, wo eine Serveranwendung und ein passendes Kommandozeilentool in einem Repository liegt, das einfach in zwei Binaries kompiliert wird, da ist das am Anfang ein bisschen schwierig, wie man da den Code aufteilt. Also gerade auch wenn man shared components hat.

Christoph Iserlohn: Wo der Philipp gerade den Debugger erwähnt hat, da finde ich wichtig, dass man vielleicht nochmal erwähnt, dass es da genau umgekehrt ist zu den Generics. Der ist nicht drin, weil die Erfinder sagen, man braucht eigentlich keinen Debugger, sondern mit printf und gutem Testing findet man das auch. Ist jetzt ein bisschen überspitzt gesagt, aber die haben sich schon öfter dagegen ausgesprochen und das heißt der wird wahrscheinlich auch nicht so Einzug finden. Also außer als third party, da gibt es auch welche, aber das ist natürlich wieder nicht so gut, als wenn es direkt drinnen ist. Und das würde ich vielleicht auch nochmal ergänzen wollen zudem, wo ich sage, die Standardbibliothek ist gut, auch die Tools, die mitgeliefert werden. Der Philipp hat gerade den Go-Formator erwähnt, der den Quelltext formatiert und da jede Streitigkeit und Flamewar beilegt, aber das hat auch noch ganz andere, ganz coole Tools dabei, wie zum Beispiel einen Profiler, der ganz… also der sehr brauchbar ist. Es hat dabei ein Testing Tool, also man braucht sich auch nicht über die Unit Test Bibliothek streiten, Testing ist fest miteingebaut. Auch das Ganze, was man für den Build braucht, also wenn man in Java jetzt mit Maven bauen würde oder mit Gradle oder in anderen Sprachen, mit… weiß ich nicht, welche Buildtools es da alles so gibt, das ist alles mit drin. Es gibt ein Tool, um race condition zu finden in seinem Code, also Concurrency zu überprüfen. Das Tooling, das dabei…, also was sozusagen mitgeliefert wird, ist auch sehr gut, würde ich auch nicht missen wollen und unterscheidet sich auch von vielen anderen Sprachen, wo das alles so third party Sachen sind.

Lucas Dohmen: Cool. Ja, dann sind wir ja eigentlich schon mitten bei den Besonderheiten. Also wir hatten jetzt schon über die Standardbibliothek geredet, über die Tools. Eins was du eben schon erwähnt hattest, Christoph, war auch die Concurrency. Was macht denn da Go so besonders? Was ist daran so cool? Was ist die… Warum ist das besonders gut?

Christoph Iserlohn: Ja, also Go hat Concurrency sozusagen als Build-In drinnen, in vielen anderen Programmiersprachen gibt es dafür keine Konstrukte, beziehungsweise man hat dafür so Betriebssystem Konstrukte daran getackert. Also ich kann aus Java ein Thread starten oder auch aus Python oder aus Ruby wahrscheinlich auch, das sind dann aber sozusagen…, wahrscheinlich geht man dann immer drei Abstraktionen runter, weil das Betriebssystem ähnlich ist. Und Go hat das halt, sowas eingebaut, und zwar sind das… eigentlich sind es nur zwei relativ einfache Konstrukte. Das ist die Goroutine und der Channel. Und theoretisch basiert das auf dem Konstrukt von communicating sequential processes von Tony Hoare, dem Quicksort Erfinder. Der da ein theoretisches Model zu beschrieben hat, das erfüllt jetzt nicht alles von diesem Model, aber es lehnt sich daran an und sind halt, wie gesagt, Goroutines und Channels. Und Goroutine ist dabei einfach ein Konstrukt, mit dem ich etwas nebenläufig ausführen lassen kann und das geht ganz einfach, weil ich habe wenn ich vor eine Funktion oder vor einen Funktionsaufruf das Schlüsselwort ‚go‘ schreibe, dann wird diese Funktion halt in einem anderen Thread nebenläufig zu dem Hauptprogramm ausgeführt und das macht es halt jetzt einfach, ohne dass ich irgendwie eine use thread, thread run und sonst was alles schreiben muss, sondern einfach einen Funktionsaufruf mit einem weiter Schlüsselwort. Und das andere sind Channels, das sind Konstrukte womit Goroutinen untereinander mit kommunizieren können, weil normalerweise ist das Problem ja bei Concurrency, dass es sehr Fehleranfällig ist, wenn ich mit verschiedenen Threads auf dem gleichen Arbeitsspeicher, also shared memory arbeite, dann schleichen sich ganz leicht Fehler ein, die man auch sehr schwer findet. Und der Channel ist halt einfach eine Möglichkeit, das ist auch ein Datentyp, den kann ich so konstruieren und einer Goroutine mitnehmen und dann kann ich über den Channel halt Daten an einen… Also ein Channel hat immer einen Producer und Consumer, einer steckt da was rein und der andere kann es auslesen und dann kann ich den halt entsprechend den Goroutine mitnehmen und die können sich unterhalten und die Sachen werden dann normalerweise erstmal rumkopiert. Und dann habe ich nicht das Problem, dass ich irgendwie auf shared memory arbeite. Und das ist einfach auch nur ein Typ, den mache ich jetzt mit so einem NewChannel Konstrukt, der ist auch noch typisiert, also über einen Channel kann ich nur einen Datentyp schicken. Also ich kann zum Beispiel sagen, es gibt einen Channel für Ints und einen Channel für Strings und dann kann ich der Goroutine ihre Daten dann schicken und die kann die bearbeiten. Und normalerweise gebe ich der dann auch mehr als einen Channel mit, also einen für Input oder vielleicht auch mehrere für Inputs, wenn ich verschiedene Typen habe und einen auch, so einen Back Channel, wo der sagen kann zum Beispiel: Ich bin jetzt fertig. Oder sowas.

Lucas Dohmen: Das heißt also der Channel hat eine Richtung?

Christoph Iserlohn: Der Channel hat eine Richtung erstmal und von daher passt das ganz gut, um die typischen Concurrency Fehler auszumachen. Und wie gesagt, da sind einfach nur zwei Konstrukte. Und das andere, was man erwähnen sollte mit Concurrency im Zusammenhang mit Go ist, dass die sich nicht auf dem Betriebssystem Scheduler verlassen, sondern dass die Goroutines über einen eigenen Scheduler gefahren werden und dann kann man dem Go Binary am Anfang mitgeben, wie viele Betriebssystem CPUs er sozusagen, wie viele Threads er benutzen soll. Also dann kann ich sagen: Du nimmst jetzt acht Threads und darauf schedulest du deine Goroutines und das hat den Vorteil, dass die viel leichtgewichtiger sind als so ein typischer Betriebssystem Thread. Also ist ohne Probleme möglich mehre Millionen Goroutines aus einem Raspberry Pi, den ich hier vor mir stehen habe, zu starten, der jetzt, gegenüber bei einem normalen Rechner, relativ schwach ist, auf einen normalen Rechner aber mehrere Millionen Threads zu starten von Betriebssystemen, ist halt deutlich schwerer. Und das macht es halt relativ leicht in Go Sachen zu schreiben, die Concurrency benötigen.

Lucas Dohmen: Also das klingt ja auf jeden Fall schonmal beeindruckend. Wie ist das mit den Channeln? Ist das immer nur eine auf der einen Seite und eine auf der anderen Seite? Oder kann man damit auch andere Konstrukte bauen, dass man dann irgendwie verschiedene Consumer hat und einen Producer oder sowas? Geht das auch?

Christoph Iserlohn: Das geht auch und das ist auch synchronisiert. Also das heißt, wenn ich… Sagen wir mal ich habe einen Producer und der schiebt da irgendwelche Tasks rein oder Datenstrukturen, die langwierig bearbeitet werden müssen und der kann die halt relativ schnell produzieren, dann brauche ich halt viele Consumer, die die abnehmen und dann bearbeiten. Und diesen Channel könnte ich jetzt jedem Consumer geben und die können alle darauf lesen. Und das ist synchronisiert, also es kann nicht sein, dass auf einem Channel dann zwei gleichzeitig lesen und dasselbe da rausholen, das kriegt nur einer. Also die sind synchronisiert. Diese Channels sind auch in zwei Varianten verfügbar, also mit Buffer oder ohne. Das heißt ohne Buffer ist das so eine Art Rendez-Vous Point, wenn ich etwas reinschreibe, dann bin ich immer blockiert, bis jemand das abholt, ohne Buffer. Wenn ich einen Buffer habe, dann kann ich die Größe bestimmen. Sagen wir mal, wenn ich einen Channel mit Buffer Größe von zehn, dann kann ich halt da reinschreiben und wenn der Buffer noch nicht voll ist, dann kehrt auch der Writer sofort zurück. Und beim Lesen ist es auch so, dass ich sozusagen darauf warten kann bis etwas verfügbar ist. Also ich kann da blockieren, muss das aber nicht. Also ich kann auch mit einem Timeout arbeiten und sagen: Jetzt bitte nicht.

Lucas Dohmen: Cool. Okay, was gibt es noch für Besonderheiten neben den Concurrency Model von Go?

Philipp Haußleiter: Eine Besonderheit, die wir vielleicht noch gar nicht so explizit erwähnt haben, ist, dass Go halt eine kompilierte Sprache ist. Das heißt letztendlich ist das Ergebnis immer ein Binary wo halt alle Abhängigkeiten auch enthalten sind und das hat halt den Vorteil, dass irgendwelche Zugriffsfehler zu compile-Zeit auch entdeckt werden. Was halt auch die Anforderungen an Cross-Plattformentwicklung ein bisschen vergrößert. Das heißt man kann cross-compiling machen, also für ein Mac zum Beispiel, für Windows oder Linux Binaries bauen, aber für… Im Vergleich zu Sprachen, die halt zur Laufzeit Dinge auswerten oder die halt einfach dann… wo man einfach Prozess startet und man entwickelt dann nebenher und der Prozess aktualisiert sich halt automatisch, wie es halt bei JavaScript zum Beispiel auch möglich ist, ist das halt auch ein bisschen ungewohnt. Aber wie gesagt, wenn man eher aus der C/C++ Ecke kommt, ist das halt auch eher gängig.

Christoph Iserlohn: Also das ist gegenüber… Also man sollte da vielleicht unterscheiden. Der Philipp sagt ja gerade, dass das nativ kompiliert wird, also da kommt irgendwie dann am Ende Maschinencode raus, da ist das cross-compiling super. Also wer schonmal versucht hat eine C oder C++ cross-compiler Chain aufzubauen, der weiß wie viel Leid da drinsteckt, bis man das hat. Und das ist einfach bei dem Go Compiler miteingebaut, ich kann kompilieren für andere Prozesse Architekturen und für andere Betriebssysteme. Und das ist einfach nur zwei Umgebungsvariablen mehr, wo ich dann schreibe, das ist jetzt für ARM und Linux, dann habe ich das auf meinem Raspberry Pi. Da ist das meilenweit vor allem, was sonst so nativ kompiliert. Der Vergleich ist, was Philipp ja auch erwähnt hat mit JavaScript oder anderen Sachen, also die jetzt direkt aus dem Quelltext ausgeführt werden, wie bei JavaScript oder die Bytecode haben, wie Java, die sind ja sowieso schon eigentlich kompatibel für verschiedene Plattformen. Weil dieser Bytecode halt jeweils auf der entsprechenden virtuellen Maschine ausgeführt wird, wenn die auf dem Rechner verfügbar ist, also auf einem ARM Rechner unter Linux oder unter, auf meinem Mac Notebook hier, dann ist das ja kein Problem. Aber ich würde das schon als sehr besonderes Merkmal auch gerne hervorheben, dass das für eine Sprache, die native Binaries raushaut, absolut genial ist.

Lucas Dohmen: Cool. Sonst noch etwas besonders an der Sprache?

Christoph Iserlohn: Ja, wo wir noch beim compiling waren würde ich noch gerne erwähnen, dass diese Binaries halt statisch gelinkt sind. Das heißt da sind keine externen Bibliotheken drin, wenn ich jetzt nicht ein C-Binding oder ähnliches benutze, dann muss diese C Library natürlich da sein, aber normalerweise sind die nicht da. Das macht das cross-compiling unter anderem auch so einfach, das macht aber auch das Deployment sehr einfach, weil ich habe keine Abhängigkeiten. Das heißt, wenn ich dir jetzt auf meinem Mac etwas kompiliere und dir das schicke, dann kannst du das sofort auf deinem Mac ausführen, ohne dass du vielleicht irgendwelche Bibliothek X in Version Y da zur Verfügung haben musst.

Lucas Dohmen: Cool. Gut, dann lasst uns doch mal in das nächste Thema reinschauen. Dependency Management, darüber habe ich bisher eher negative Sachen aus der Go Welt gehört, wie funktioniert Dependency Management in Go? Ist das so schlimm wie man hört? Ist es gut/schlecht? Wie funktioniert es?

Christoph Iserlohn: Also es war sehr, sehr schlimm, das haben wir vorhin vielleicht auch so ein bisschen unter den Tisch fallen lassen. Es war so, dass so ein minimales Dependency Management eingebaut war und das heißt wenn man irgendwie einen Import einer Bibliothek hatte, die Bibliotheken wurden dann über die URL angesprochen, sagen wir mal ein GitHub URL. Und dann konnte man mit dem Kommando ‚go get‘ sich diese Bibliothek auf den Rechner laden und die war dann da für das Kompilieren verfügbar. Das Problem war, man hat immer den neusten Stand einfach runtergeladen. Das heißt, wenn ich jetzt etwas kompiliere, Philipp checkt dann etwas ein und dann kompilierst du das, dann hast du vielleicht einen anderen Stand, weil die Dependency erhöht war. Das war, sagen wir so, bescheiden und auch nicht dem Stand der Technik, auch vor 10 Jahren, wo das rausgekommen ist, entsprechend. Weil da hatten fast alle anderen Sprachen auch schon irgend sowas wie Dependency Management eingebaut. Jetzt ist es so, dass es die Go Modules gibt und ein Standard, wo es auch sowas wie Versionierung gibt, was dieses Problem jetzt gelöst hat. Also wenn ich jetzt damit anfange habe ich kein Problem, habe ich das noch vor ein paar Jahren gemacht, hatte ich richtig ein großes Problem und habe ich jetzt noch mit irgendwelcher Legacy Software zu tun, es gibt noch genügend Projekte, die halt noch nicht auf diese Module umgestellt haben, dann könnte ich ein Problem bekommen.

Philipp Haußleiter: Also man muss vielleicht dazu auch noch sagen, es gibt bei Go nicht, wie bei anderen Sprachen, zum Beispiel bei Node oder Java, irgendwie ein zusätzliches Registrysystem, wo man halt fertig kompilierte Pakete runterlädt, sondern das Abhängigkeitssystem war auch schon von Anfang an darauf ausgelegt, dass es halt einfach ein Git Repository ist als Default, also das muss nicht bei GitHub sein, aber das sind halt…, der größte Teil der Abhängigkeiten liegt halt bei GitHub. Und das hat am Anfang halt auch dazu geführt, dass die eigene… die lokale Entwicklungsumgebung dementsprechend aufgebaut ist. Also es gibt ein GOROOT Variable und basierend auf dieser Variable wurden dann halt die Abhängigkeiten auch aufgelöst. Was auch ein bisschen vielleicht darauf zurückzuführen ist, dass Google selber ja auch dieses one Repository hat und auf diesem Ansatz her die unterschiedlichen Projekte entwickelt werden. Und mit diesem Go Modules System wurde halt auch so eine zusätzliche Menge an Metadaten eingefügt, wo halt zum einen die Abhängigkeiten an einer Stelle definiert sind und wo zum anderen halt auch Checksummen hinterlegt sind, also ähnlich wie bei Node diese package-lock Datei. Und dann halt auch neben der eigentlichen Versionierung nochmal ein bisschen sicherstellen können, dass halt auch ein spezifischer Hash auch wirklich als Abhängigkeit rausgezogen wird und insgesamt hat das Dinge vereinfacht, weil vorher war man sich nie sicher, welches Dependency System sollte ich jetzt verwenden? Also ich habe am Anfang, ich glaube Glide war ein relativ großes, was man damals so gefunden hatte. Es gab noch ein anderes, das fällt mir gerade nicht ein, aber man hatte dann halt immer die Wahl: Baut man jetzt irgendwie zwei Dependency Systeme ein, um irgendwie eine breite Zielgruppe zu haben, wenn man irgendein Modul baut oder irgendeine Bibliothek. Und wie die Entscheidung gefallen ist sei mal dahingestellt, aber es ist halt gut und eigentlich auch im Sinne der Sprache gewesen, dass sie gefallen ist.

Lucas Dohmen: Okay, das heißt aber, wenn man jetzt auf die ganze Community guckt, auf das Ökosystem, in dem Bereich hat sich jetzt aber das so ergeben, dass alle Leute diesem neuen Standard folgen? Oder ist das noch was, was noch in der Luft hängt und oft findet man doch noch Sachen, die man mit dem modernen System nicht verwenden kann?

Christoph Iserlohn: Also da muss man zwei Sachen vielleicht auseinanderhalten, man… a) Was ich vorhin schon erwähnt habe, ist natürlich, man findet noch jede Menge Sachen, die das noch nicht unterstützen. Aber auf der anderen Seite, das Module System kommt mit denen auch klar, also das kann dir auch einfach noch per git fetch sich auch noch holen. Also es ist sozusagen rückwärts-kompatibel. Natürlich tritt man dann sich die Probleme von fehlender Versionierung und sowas ein, aber es ist jetzt nicht so, dass ich sage, wenn ich jetzt Modules mache, ist das Alte für mich weg. Also so gesehen ist das Problem ein bisschen gelindert, aber es ist halt auch nicht komplett aus der Welt. Vielleicht reden wir mal kurz darüber, dass dieses Ökosystem, ist halt auch sehr groß. Es gibt viele Bibliotheken im Go Bereich und auch sehr viele gute Sachen. Von daher will man wahrscheinlich in seinen Projekten immer auf third party Libraries in irgendeiner Form zurückgreifen und nicht die gesamte Welt immer neu erfinden. Das ist ganz gut und wie gesagt, es bewegt sich hin zu dem Modulsystem. Das liegt auch daran, dass das… diese Go Modules halt fest im Tooling integriert sind, also ist ein Bestandteil von Go. Es gibt also… Es ist halt nicht wie bei Node und npm, dass das zwei verschiedene Dinge sind, die man zwar auch immer fast gleichsetzt und npm auch von Node mit ausgeliefert sind, aber das sind halt zwei Projekte von verschiedenen Leuten, die das maintainen, so ist es nicht. Oder in der Java Welt ist es ja auch so, dass Java erstmal keine Dependency Management mitbringt, sondern da hat man sich halt auf Maven und Gradle und was es da sonst nicht an Tools gibt, geeinigt, die aber auch sozusagen dieselbe Serverseite bedienen. Also die können dieselben Repositories benutzen. Und bei Go ist es halt Bestandteil der Sprache jetzt, da gibt es halt keine echten Alternativen mehr. Und da kommen wir vielleicht auf den Punkt Community, der… Die Community ist groß, sie ist auch sehr hilfreich, aber was man da gesehen hat, bei diesem Thema Dependency Management, ist halt auch, dass Google da noch einen ganz großen Einfluss hat, der nicht immer gut ist. Und zwar war es so, dass es diese ganzen Alternativen, von denen der Philipp gerade gesprochen hat, das waren ja alles third party Projekte. Und die haben auch gesehen: Das ist jetzt problematisch, wenn wir jetzt hier X Produkte haben und Projekte, die diese Probleme lösen wollen, setzten wir uns doch mal zusammen, wie das denn vernünftig sein könnte. Und die waren auch schon relativ weit und haben da viele Sachen produziert, wie einzelne Tools kompatibel werden können und sozusagen Protokolle definiert, damit man vielleicht auch verschiedene Tools nutzen kann, die dann dasselbe Protokoll sprechen. Aber einer der Google Mitarbeiter hat dann gesagt: Ich mach das jetzt mal eben. Und hat das so an denen vorbei, ohne die groß zu konsultieren, sozusagen runterprogrammiert, dazu so ein paar Design Sachen, also Design Dokumente geschrieben, warum das so ist und hat dann das einfach… sozusagen hat man das einfach als Standard gesetzt mit der… die Community hat man da übergangen. Es gab auch eine große Aufruhr und von daher bin ich so ein bisschen gespalten, Google sagt zwar immer: Ja, wir stellen jetzt gar nicht mehr die meisten Maintainer, weil es mehr Commits von anderen Leuten als von Google Mitarbeitern gibt. Wenn man da aber mal reinschaut, also die Kernthemen, das sind doch eher die Google Mitarbeiter und die ganzen vielen anderen Commits sind dann sowas wie Typos in der Doku oder ähnliches. Also von daher, ich bin da ein bisschen gespalten. Die Community ist gut, der Google Einfluss ist mir noch deutlich zu groß. Also ich hätte es gerne, dass sowas zum Beispiel, wie bei anderen Sachen, in eine Stiftung oder ähnliches überführt wird, weil Go wird ja breit eingesetzt und das kann man sich jetzt nicht einfach so wegdenken. Wenn das verschwinden würde, wäre… kämen viele Projekte in arge Schwierigkeiten.

Lucas Dohmen: Okay. Und wenn wir jetzt mal ein bisschen in die Zukunft schauen, was kommt in Go auf uns zu? Worauf freut ihr euch schon? Ihr habt schon Generics angedeutet. Was kommt?

Christoph Iserlohn: Ja, Generics sollen kommen, dafür gab es schonmal den ersten Entwurf, den man so, auch prototypisch, implementiert hat. Da hat man so einiges gesehen, was da nicht so funktioniert hat. Das hat man wieder verworfen, jetzt gibt es einen, der… Also der wahrscheinlich das Rennen machen wird, weil der bis jetzt wenig Probleme aufgezeigt hat. Das wurde auch ganz gut entwickelt mit der Community, da gibt es Design Dokumente, an denen sich jeder beteiligen kann. Die kann jeder kommentieren, Anmerkungen zu machen, Rückmeldung geben, wie denn diese Prototypen funktionieren, da läuft es ganz gut. Das hat natürlich auch mit den Grund, dass… da gab es jetzt keine Alternativen in der Community, die schon einer mal ausprogrammiert hat, von daher ist es da vielleicht leichter einen Konsens zu finden. Das ist halt so eine Frage, also es gibt dieses Versprechen der Rückwärtskompatibilität, das was mit Go 1, also ab Go 1.0 kompiliert wurde, sollte jetzt eigentlich auch noch funktionieren. Also der Quellcode sollte von Go 1.0 Projekt jetzt mit der aktuellen Go 1.15, sind wir jetzt, auch noch funktionieren. Und so ist das bis jetzt eigentlich auch. Und Go 2, was so am Horizont steht, ist halt die erste Version, die mit dieser Kompatibilität brechen kann, wenn sie will. Man versucht das weitgehend zu vermeiden, also erst hieß es Go 2 wird der große Wurf. Jetzt sind vier Sachen, die so in kleinen Schritten kommen, die gar nicht unbedingt mit der Kompatibilität zu Go 1 brechen. Und ja, was kommt sonst noch? Kleinigkeiten, also man will dieses Error-Handling verbessern, will aber… Also exceptions sollen nicht kommen, aber sich da etwas überlegen, um da ein bisschen mehr Komfort für den Programmierer zu machen, anstatt irgendwie in der Funktion drei Mal if error, dann so und so, zu machen, sondern dass wir das dann irgendwie ein bisschen erleichtern. Aber da steht noch nicht fest, was da passieren wird.

Lucas Dohmen: Also man kann schon sagen, dass auch eher konservativ Änderungen eingefügt werden in die Sprache?

Christoph Iserlohn: Also extrem konservativ, wie gesagt diese Rückwärtskompatibilität ist den Go Leuten ganz wichtig und das Go 2 der große Bruch werden wird, damit hat man jetzt auch gebrochen, sondern man will es jetzt doch schon eher evolutionär machen.

Lucas Dohmen: Okay, alles klar.

Philipp Haußleiter: Zum Thema Generics kann man vielleicht noch erwähnen, es gibt ein Tool, was sie rausgebracht haben. Das heißt go2go und gibt es halt auch als Playground, also als Webanwendung, wo man halt eigenen Code auch schonmal dagegen überprüfen kann, wie er dann mit der neuen Generics Funktionalität funktionieren würde. Und da denke ich, dass spiegelt so ein bisschen die Erfahrung wieder, die sie mit den Modularisierungssystem gehabt haben und mittlerweile sieht man halt schon, dass sie sich zumindest nach außen hin bemühen das Ganze transparenter und vielleicht ein bisschen klein-schrittiger durchzuführen.

Lucas Dohmen: Cool. Wenn ich so eine neue Programmiersprache höre, dann will ich immer so ein bisschen einordnen, wofür ist die denn cool geeignet? Worin ist sie besonders gut? Und vielleicht, worin ist sie nicht so gut? Wo kann ich sie nicht so gut für benutzen? Wie würde ihr denn Go einsortieren, so im Werkzeugkasten?

Philipp Haußleiter: Also ich kann relativ schnell sagen, was mir gefehlt hat, was ich dann in Go gefunden habe. Und zwar hatte ich halt immer zwei Teile, wo man programmiertechnisch unterwegs war, das eine sind diese klassischen größeren Back-End Web Anwendungen, wo man vielleicht dann auch ein eigenes Design Team hat, man hat irgendwie Leute, die die Businesslogik definieren und der andere Bereich sind dann immer so diese Tooling Systeme. Sei es irgendein API-Server, wo man mal eben eine Datenbank anwenden muss oder irgendwelche zwei APIs miteinander verbinden muss und dann etwas zurückgeben muss. Oder das andere sind halt diese typischen Kommandozeilen Tools, da einfach kleinere Programme, alles was dann halt über 200 Zeilen Bash Code geht, wo man halt sagt: Eigentlich möchte ich das gerne vernünftig umsetzen. Und bei den beiden letzteren Beispielen war halt immer mein großes Problem: Wie kann ich die Abhängigkeiten managen, dass es halt auch ein vielleicht nicht technischer Anwender ausführen kann? Und B: Wie kriege ich es so hin, dass das Ausführen selber möglichst einfach ist? Dadurch, dass ich Go halt einmal kompilieren kann und ich sicherstellen kann, dass das auf einem bestimmten System ausgeführt werden kann, kann ich halt dieses Binary halt irgendwie zur Verfügung stellen. Ein Tool, das ich sehr gerne verwende, ist halt so eine automatische Updatefunktion, die es halt als Modul auch gibt bei Go und damit ist halt sowohl die Auslieferung, als auch die Ausführung wesentlich einfacher, als das vielleicht bei Java oder halt allen Sprachen, die halt mehr Anforderungen an die Ausführungsumgebung benötigen. Das war eigentlich so der Hauptgrund, wo ich halt… Ja, wo für mich halt ein Problem war, was ich irgendwie gerne lösen wollte.

Lucas Dohmen: Cool. Und du Christoph?

Christoph Iserlohn: Ja, also für mich ist Go die Sprache der Cloud. Und zwar, was soll das heißen? Die Sprache der Cloud im Sinne von, wie sieht jetzt so eine typische Architektur aus? Wenn ich irgendwas in die Cloud schiebe, dann habe ich wahrscheinlich eine Reihe von Services, Microservices oder SCS, was man auch immer da hat. Aber wahrscheinlich irgendeine Art von verteilen System und dafür halte ich Go… Also für mich ist da Go sehr gut, um solche Sachen zu implementieren, weil sie alle halt so einer, von der Standardbibliothek sozusagen, guten Server Stack haben. Also ich brauche nicht jetzt sozusagen mein Java Programm in den Tomcat bringen oder mit Spring Boot ein Tomcat starten oder so, sondern ich habe halt schon einen Produktionsreifen HTTP/2 Server da, der auch TLS sprechen kann, das ist sozusagen dabei. Ich habe eine Templating Bibliothek dabei, wenn ich HTML ausliefern will typischerweise, dann kann ich das auch ganz leicht machen. Das heißt dafür ist das ganz gut geeignet, aber es hat noch so ein paar andere Vorteile, die ich jetzt speziell so auf das Thema Cloud ziehen würde. Das ist einmal das Deployment. Ich meine das wird in anderen Sprachen natürlich gelöst dafür, dass man alles in einen Container packt. Aber das statische Binary, das kann ich halt sozusagen auf jede Plattform schieben, das kann ich auf eine VM schieben, dass kann ich auf Bare Metal schieben und das kann ich in einen Container schieben und der ist nur from Scratch. Das heißt der Container ist auch extrem klein, weil eigentlich nur diese Binary drinsteht und vielleicht noch drei Konfigurationsdateien oder wenn ich etwas ausliefre an HTML, vielleicht die Templates. Obwohl ich die auch… es dafür Tool gibt, dass ich die in diese Binary packen kann, dann brauch ich sie noch nicht mal dahaben. Das ist dann sehr klein, was den Vorteil hat, dass ich nicht irgendwelche riesigen Container rumschicken muss in so einem Cloud Deployment. Also wenn wir von Cloud sprechen, haben wir auch oft den Fall, dass wir auf so einer Plattform wie Kubernetes oder so sind. Also da habe ich den Vorteil erstmal, dass er klein ist und das andere ist, dass es a) schnell startet und b) auch sehr schnell läuft und wenig Speicher verbraucht. Wozu ist das wichtig? Also schnell starten ist halt, das ist immer so ein Problem vor allem bei größeren JVM Services, dass die relativ lange brauchen für den Start. Und wenn ich so eine, sagen wir mal, ich nenne das jetzt mal Cloud Architektur habe und die auf so ein Continuous Deployment fahre, ist das schlecht, wenn ich irgendwie hundertmal am Tag deployen will oder sei es auch zwanzigmal am Tag und dann brauchen die Container halt immer ewig, bis die oben sind. Das ist halt ganz gut, weil die sind eigentlich instantan da. Das andere ist, die verbrauchen weniger Speicher als ein typisches JVM Projekt und sie laufen von der Geschwindigkeit wahrscheinlich ähnlich schnell. Nicht groß schneller, auch wenn sie nativ kompiliert sind, also da ist der JIT Compiler von Java schon ziemlich gut, aber der muss auch erstmal wieder anlaufen. Das dauert was bis der warmgelaufen ist, vielleicht ist dazwischen schon das nächste Deployment gekommen. Bei Go starte ich halt mit voller Geschwindigkeit dabei und für das meiste ist es schnell genug. Also YouTube hat, gehört ja auch zu Google, hat eine ganze Reihe ihrer Server halt auch in Go umgeschrieben, die waren vorher C++ und die konnte aber keiner mehr warten. Also hat man Go genommen und die Geschwindigkeit ist dafür ausreichend. Und ich möchte gern mal in einem Projekt sein, wo ich sage: Ich brauch YouTube Skalierung und deren Performance, also von daher passt das ganz gut. Ja und noch ein Beispiel, prominentes Beispiel, die Referenzimplementierung hier für den Corona Server, den Google jetzt rausgebracht hat, die ist auch in Go geschrieben. Also alles was mit Services, mit Servern zu tun hat oder Microservice oder SCS und das irgendwie mit einem Netzwerk spricht und vielleicht HTML oder JSON rausspuckt, kann man damit super machen.

Lucas Dohmen: Ja, also ich meine Go ist ja schon auffällig präsent in vielen Bereichen, wie auch jetzt neuen Datenbanken, wie jetzt CockroachDB oder auch so Monitoring Tools wie Prometheus, da gibt es ja mittlerweile viele Sachen. Was meint ihr ist dafür der Grund, dass so viele von solchen Ops Tools in Go geschrieben sind?

Philipp Haußleiter: Also ein großer Punkt ist natürlich, dass Go initial auch dafür entwickelt wurde diese Infrastrukturthemen auch zu behandeln. Was halt dazu geführt hat, dass halt viele Dinge in der Sprache schon eingebaut sind, die man vielleicht in Java oder Ruby durch zusätzlich Module erst umsetzen muss. Einen zweiten großen Punkt sehe ich halt auch in der sehr einfachen Einbindung von C Programmen und C Bibliotheken, gerade auch wenn man im Unix Umfeld unterwegs ist, hat man eigentlich standardmäßig für alles irgendwelche Header Files, wo man dann die entsprechende Bibliothek einbinden kann und darüber dann halt auch sehr hardwarenah die Dinge umzusetzen. Noch als Ergänzung zu Christoph, wollte ich noch sagen, dass auch dieser Ansatz, dass man Fehler in Go ja nun explizit behandeln muss und dass man dementsprechend auch so eine fail fast Ansatz verfolgt, spricht auch aus meiner Sicht sehr dafür, dass das Ganze sehr geeignet ist, um diesen Cloud Ansatz zu fahren. Also diese Situation, wo man bei einer Java Anwendung irgendwie so einen halb toten Zustand hat, die keine Anwendung keine Requests mehr annimmt, aber irgendwie doch noch da ist, die habe ich bei einer Go Anwendung halt auch noch nie erlebt. Also entweder dann komplett stirbt oder halt da ist und funktioniert. Das macht den Zustand eines Service generell irgendwie leichter abschätzbar.

Christoph Iserlohn: Also was noch ein Grund ist, warum das für dieses ganze Cloud Tooling gut geeignet ist und warum auch Docker und so andere containernahe Software das Go benutzt, ist halt, dass ich mit Go auch Betriebssystemfunktionen aufrufen kann, ohne über die libc zu gehen. Das heißt also, Docker basiert ja darauf, dass ich irgendwelche Linux Kernel Funktionalität nehme, um einen Prozess zu isolieren. Also ich habe diese cgroups und Namespaces, das sind Kernel Features und die kann ich sonst nur mit libc oder sowas C raus ansprechen. Und in anderen Sprachen, wie der JVM, Ruby und sonst wie, habe ich das nicht, da brauche ich noch irgendwie libc Bindings dafür. Bin dann halt wieder abhängig von dem jeweiligen System und von der jeweiligen libc. Und mit Go kann ich das umgehen und direkt System, also Kernel Routinen aufrufen. Und das macht es natürlich an der Stelle ganz praktisch, wenn ich so eine Container Implementierung mache. Also ich glaube das war ein Grund auch, warum Docker das gemacht hat, auch wenn jetzt auch eine Bibliothek für dieses ganze Containerzeug nehmen, der das anspricht. Aber das ist auf jeden Fall ein Grund dafür, warum das auch da sich gut durchgesetzt hat.

Lucas Dohmen: Cool. Alles klar, dann habt ihr jetzt alle meine Frage beantwortet. Liegt euch noch irgendetwas auf dem Herzen? Wollt ihr noch irgendetwas über Go teilen? Oder sind wir durch für heute?

Christoph Iserlohn: Ich glaube der Philipp will bestimmt noch etwas sagen über GUI Programmierung mit Go.

Lucas Dohmen: Okay, cool.

Philipp Haußleiter: Naja, es heißt ja immer, dass Go nur für Back-End Systeme geeignet ist. Und dadurch, dass man halt C Bibliotheken einbinden kann, ist es halt relativ einfach jetzt unter macOS zum Beispiel Cocoa zu verwenden oder unter Linux GTK. Für Windows gibt es auch Möglichkeiten. Es gibt auch Projekte, die jetzt versuchen zu Electron ein Gegenmodell zu etablieren. Also einfach eine WebView zu starten. Natürlich ist es so, dass man sich dann auch mehr mit dem Betriebssystemspezifika auseinandersetzten muss, weil man an irgendeinen Punkt ist halt so, als würde man sich selber in C mit den Bibliotheken befassen. Aber ich glaube dadurch, dass das nicht der primäre Use Case ist, der für den diese Sprache verwendet wird, ist es halt auch eher eine Ergänzung.

Christoph Iserlohn: Was ich noch sagen würde ist, dass jeder der sich mal auf Go einlassen will/sollte/muss, wirklich versuchen sollte sich auf die Paradigmen von Go einzustellen. Also ich habe das oft erlebt, dass also… dass die eine Seite, die kommen halt von C oder C++ und die sagen: Das ist ja irgendwie hier High Level, ich will meinen Speicher unter Kontrolle haben und sonst irgendwie noch mehr Low Level Kontrolle haben. Oder von C++, jetzt habe ich ja jetzt hier keine Templates mehr und das ist ja alles der totale Rückschritt. Von der Java Seite genauso: Jetzt gibt es keine Generics mehr und ich habe kein Streaming API. Das stimmt auch alles, aber ich kann mit Go nichts Vernünftiges machen, wenn ich mich nicht sozusagen auf dessen Designprinzipien auch mal einlasse. Ich meine, das gilt wahrscheinlich für jede Sprache, die man neu lernt, dass man sich drauf einlassen muss, aber die besitzt halt so einen Sweetspot, der eigentlich von anderen Sprachen besetzt ist, aber das ist nicht wie diese anderen Sprachen. Also wenn man sich nicht drauf einlässt, dann wird das nichts. Also wenn ich jetzt jedes Mal drum rumfluche, dass ich jetzt keine exceptions mehr habe, dann werde ich damit nicht glücklich. Aber man kann auch ganz gut ohne die leben und vernünftige Programme schreiben.

Lucas Dohmen: Cool. Ja, dann danke ich euch beiden für den tollen Überblick. Ich habe jetzt mehr verstanden, warum ich Go mir vielleicht doch mal anschauen sollte. Und ja, den Hörerinnen und Hörern sage ich mal: Bis zum nächsten Mal! Auf Wiedersehen!