Go ist immer noch nicht gut
(blog.habets.se)- Mehrere Entscheidungen im Sprachdesign von Go wurden unnötig getroffen oder unter Ignorieren bestehender Erfahrungen gefällt
- Das Problem der Verwaltung des Gültigkeitsbereichs von Fehler-Variablen erschwert die Lesbarkeit des Codes und das Auffinden von Bugs
- In mehreren Bereichen wie der Doppelnatur von
nil, Speicherverbrauch und Code-Portabilität zeigt sich ein unintuitives Design, das nicht zur Praxis passt - Die Grenzen der
defer-Anweisung und die Art der Ausnahmebehandlung in der Standardbibliothek erschweren es, Exception-Sicherheit zu gewährleisten - Aufgestaute Probleme wie mangelhafte Speicherverwaltung und UTF-8-Verarbeitung wirken sich langfristig negativ auf die Qualität von Go-Codebasen aus
Langfristige Kritik an der Go-Sprache
- Wie ich bereits in früheren Beiträgen (Why Go is not my favourite language, Go programs are not portable) dargelegt habe, weise ich seit mehr als zehn Jahren auf verschiedene Probleme der Go-Sprache hin
- Besonders bedauerlich wirkt, dass unnötige Designentscheidungen, die bekannte Good Practices ignorieren, immer stärker ins Gewicht fallen
Die Unintuitivität des Gültigkeitsbereichs von Fehler-Variablen
- Die Go-Syntax erweitert den Gültigkeitsbereich der Fehler-Variable (
err) unnötig und erhöht damit die Wahrscheinlichkeit von Fehlern- Im Beispielcode lebt die Variable
errüber die gesamte Funktion hinweg weiter und wird wiederverwendet, was Lesbarkeit und Wartbarkeit des Codes verschlechtert - Selbst erfahrene Entwickler erleben durch solche Scope-Probleme Missverständnisse und Zeitverlust bei der Fehlersuche
- Eine Möglichkeit, Variablen angemessen lokal zu begrenzen, wird von der Syntax nicht zugelassen
- Im Beispielcode lebt die Variable
Zwei Formen von nil
- In Go gibt es die verwirrende Situation, dass
nilbei Interface-Typen und Pointer-Typen unterschiedlich funktioniert- Wie im folgenden Beispiel führen Zuweisungen von
nilans(Pointer) undi(Interface) zu inkonsistentem Verhalten, etwa weils==iunterschiedlich ausgewertet wird - Das ist ein Problem, das man bei der Behandlung von null-Werten normalerweise vermeiden möchte, und wirkt wie das Ergebnis unzureichender Überlegungen im Design
- Wie im folgenden Beispiel führen Zuweisungen von
Grenzen der Portabilität von Code
- Die Verwendung von Kommentaren für bedingte Kompilierung ist im Hinblick auf Wartbarkeit und Portabilität deutlich ineffizient
- Wer tatsächlich schon portable Software gebaut hat, weiß, dass dieser Ansatz umständlich und fehleranfällig ist
- Historisch gewachsene Erfahrungen zu Code-Portabilität und praktischen Fällen werden ignoriert
- Siehe dazu Go programs are not portable
Unklare Besitzverhältnisse bei append
- Die Beziehung zwischen der Funktion
appendund dem Besitz von Slices ist nicht klar, wodurch sich Code schwer vorhersagen lässt- Anhand eines Beispiels wird gezeigt, dass sich vorab schwer erkennen lässt, welchen Einfluss ein
appendauf einen Slice in der Funktionfootatsächlich auf das Original hat - Dadurch nimmt die Zahl sprachlicher „quirks“ zu, die man kennen muss, und das führt zu Fehlern
- Anhand eines Beispiels wird gezeigt, dass sich vorab schwer erkennen lässt, welchen Einfluss ein
Unzureichendes Design der defer-Anweisung
- Es gibt keine klare Unterstützung für das Freigeben von Ressourcen nach dem RAII-Prinzip (Resource Acquisition Is Initialization)
- Im Vergleich zu strukturierten Resource-Management-Konstrukten in Java und Python ist in Go nicht klar erkennbar, welche Ressourcen mit
deferfreigegeben werden sollten - Wie das Beispiel mit Dateiverarbeitung zeigt, muss man sogar Probleme wie Double-Close selbst behandeln, und die richtige Reihenfolge sowie Art der Freigabe bleiben unklar
- Im Vergleich zu strukturierten Resource-Management-Konstrukten in Java und Python ist in Go nicht klar erkennbar, welche Ressourcen mit
Ausnahmebehandlung in der Standardbibliothek
- Go ist strukturell so angelegt, dass es keine expliziten Exceptions unterstützt, dennoch treten Ausnahmefälle wie
panicweiterhin auf- In manchen Situationen beendet
panicdas Programm nicht vollständig, sondern wird gewissermaßen verschluckt - In der Standardbibliothek (
fmt.Print, HTTP-Server usw.) existieren Muster, in denen Ausnahmen ignoriert werden, sodass echte Exception-Sicherheit nicht garantiert werden kann - Am Ende ist exception-sicherer Code zwar zwingend nötig, aber Exceptions selbst lassen sich nicht direkt verwenden
- In manchen Situationen beendet
UTF-8-Verarbeitung und Strings
- Selbst wenn man beliebige Binärdaten in den Typ
stringsteckt, arbeitet Go ohne besondere Validierung weiter- Dadurch kann es vorkommen, dass Dateinamen aus der Zeit vor UTF-8 stillschweigend ausgelassen werden
- Bei Backups und ähnlichen Szenarien können wichtige Daten verloren gehen; der Ansatz ist zu simpel und spiegelt reale Anforderungen nicht wider
Grenzen der Speicherverwaltung
- Eine direkte Kontrolle über den RAM-Verbrauch ist schwierig, und auch die Zuverlässigkeit des GC (Garbage Collector) hat Grenzen
- Der Speicherverbrauch von Go wächst, was langfristig zu Kosten- und Performance-Problemen führt
- In Umgebungen mit mehreren Instanzen oder Containern treten Kosten- und Skalierungsprobleme tatsächlich auf
Fazit: Es hätte einen besseren Weg gegeben
- Obwohl es bereits wirksam erprobte Sprachdesigns gab, ignoriert Go sie in vielen Punkten
- Anders als bei den Problemen früher Java-Entwürfe gab es zum Zeitpunkt der Veröffentlichung von Go bereits bessere Ansätze
Referenzen
- Uber: Data race patterns in Go
- FasterThanLime: Lies we tell ourselves to keep using Golang
- FasterThanLime: I want off Mr Golang’s wild ride
1 Kommentare
Hacker-News-Kommentar
Ich nutze Go seit der Zeit vor 1.0 in fast jedem Vollzeitjob. Für Teammitglieder ist es einfach, die Grundlagen zu lernen, und es läuft meist stabil. Beim Update auf die neueste Go-Version muss man sich fast nie Sorgen machen, und die meisten nützlichen Funktionen sind standardmäßig enthalten. Die schnelle Kompilierung ist attraktiv. Nebenläufigkeit ist etwas knifflig, aber wenn man Zeit investiert, eignet es sich gut dazu, Datenflüsse auszudrücken. Das Typsystem ist meist praktisch, aber manchmal etwas wortreich. Insgesamt ist es ein verlässliches Werkzeug. Trotzdem kann ich viele der im Artikel genannten Kritikpunkte nachvollziehen. Es ist klar, dass Go an einigen Stellen zu sehr von Entwicklern der alten Schule geprägt wurde, die sich an Prinzipien festgebissen und dabei praktische Bequemlichkeit verpasst haben. Das ist natürlich nur mein Eindruck, und ich denke auch, wenn man alle Schwächen behoben hätte, wäre es vielleicht heute schlechter. Ich möchte außerdem erwähnen, dass die Stimmung in den letzten Jahren offener für das Beheben solcher Eigenheiten geworden ist. Früher hätte ich mir nie vorstellen können, dass Generics oder benutzerdefinierte Iteratoren hinzukommen. Die Kritik an RAM und Portabilität wirkt eher wie persönlicher Frust. Verbesserungen wären schön, aber dass der GC in den meisten Programmen ernsthafte Probleme verursacht, ist extrem selten, und Debugging ist auch nicht besonders schwer. Außerdem unterstützt Go fast alle wichtigen Plattformen. Allerdings stören mich Fehler- und
nil-Behandlung weiterhin. Syntax wieResult[Ok, Err]oderOptional[T]vermisse ich oftIch sehe eher das Gegenteil: Go hat nicht stur an Prinzipien festgehalten, sondern sich an der Bequemlichkeit festgebissen, sichtbare Probleme schnell zu lösen. Statt Probleme grundlegend zu analysieren und korrekt zu lösen, wirkte es so, als hätte man den Geist von „Not Invented Here“ aufgegeben und schnell etwas zusammengeschustert. Die Dateisystem-API von Go ist ein typisches Beispiel. Man braucht eine Funktion zum Öffnen von Dateien, also macht man einfach
func Open(name string) (*File, error)und fertig. Aber was, wenn der Dateiname nicht UTF-8 ist? Wenn das Problem fünf Jahre lang nicht auftaucht, kümmert man sich eben nicht darumIch habe oft das Gefühl, dass die Designprinzipien von Go zu stark auf das Ziel „Compiler einfach halten und Kompilierung schnell machen“ fokussiert sind. Die Struktur ist stärker auf Compiler und Kompilierung selbst ausgerichtet als auf Entwickler-Ergonomie
Nach 20 Jahren habe ich in einem neuen Job zum ersten Mal wieder ernsthaft eine kompilierte Sprache benutzt, nämlich Go. Vielleicht Geschmackssache, aber ehrlich gesagt hat sich das beim Schreiben teils unerquicklich angefühlt. Keine Standardargumente, die Fehlerbehandlung gefällt mir nicht, keine ordentlichen Stacktraces in Produktion. Die objektorientierte Syntax sieht unschön aus, weil man an jede Funktion diese merkwürdige Referenz hängen muss. Auch Zeiger sind lästig. Es fühlt sich letztlich an, als wäre man zu alten C/C++-Techniken zurückgekehrt. Genau die Programmieratmosphäre, die ich um 1999 im Studium hatte
Was Nebenläufigkeit angeht, ist Go meiner Erfahrung nach das einzige System, das Parallelität in einer Mehrkern-CPU-Umgebung sprachlich natürlich behandelt. Dank des CSP-artigen Goroutine/Channel-Modells lässt sich Nebenläufigkeitslogik intuitiv ausdrücken. Python ist mit GIL und kryptischen Async-Bibliotheken unerquicklich. Bei C, C++, Java usw. braucht man zusätzliche Bibliotheken außerhalb der Sprache, daher ist Schlussfolgern über Parallelität auf Sprachebene nicht einfach. Deshalb passt Go meiner Meinung nach perfekt zu HTTP-Servern oder Services. Ich kenne aus meiner Erfahrung keine ähnlich gute Alternative
Aus Entwicklersicht war die Ergonomie, also Standardisierung und Konsistenz, nahezu perfekt. Selbst über mehrere Microservice-Codebasen hinweg muss man sich keine Sorgen um unterschiedliche Stile machen, und Formatierungsdebatten entfallen. Allerdings scheint Go bei der Wahl seines eigenen Standards etwas zu sehr an alten Mustern festzuhalten. Heutige Entwickler erwarten eher funktionale Methoden wie map/filter, während Go nur Schleifen bietet, bei denen man sich leicht bei Indizes vertut. Das Typsystem ist auch nicht so intelligent wie etwa in TypeScript. Die Fehlerbehandlung ist umständlich. Ich verstehe die Sorge, dass zusätzliche Features mehr „kreative, aber schlechte Nutzungsweisen“ fördern könnten, aber mir ist auch klar geworden, dass es schwer ist, die JS-Generation von Go zu überzeugen
Ich arbeite seit über fünf Jahren intensiv an großen Golang-Projekten, und wenn man Komponenten bauen muss, bei denen der Speicherverbrauch minimiert werden soll, stößt man oft auf die schlampigen Seiten von Go. Der GC räumt nicht schnell genug auf oder die Heap-Fragmentierung wird schlimm, weil Go keinen kompaktierenden Garbage Collector hat. Deshalb versuchen wir, Allokationen vollständig zu vermeiden, was aber fehleranfällig ist. Auch Debugging ist extrem mühsam. Heap-Profile zeigen nur Informationen zu überlebenden Objekten, nicht aber den tatsächlich aufgelaufenen Müll oder Fragmentierungsdetails, sodass man auf Vermutungen angewiesen ist. Zum Beispiel zeigt eine Funktion X vielleicht nur 1 KB Heap-Allokation an, aber wenn sie in einer Schleife ständig aufgerufen wird, entstehen zig MB Müll. Also allokiert man vorab statische Buffer und verwendet sie wieder, aber dann werden Eigentumsfragen kompliziert und Lücken wie
appendtun sich auf. Man muss teils sogar die Standardbibliothek selbst neu implementieren. Ich weiß auch, dass unser Fall nicht typisch ist, aber es ist schade, weil es sich wirklich anfühlt, als würde man gegen die Sprache kämpfenIn solchen Fällen kann es sogar weniger schmerzhaft sein, den Speicher außerhalb des Heaps zu verlagern. In einer GC-Sprache ist das natürlich nicht einfach, aber statt krampfhaft C++-/Rust-artigen Code in Go nachzubauen, wäre es besser, genau diesen Teil gleich in der jeweiligen Sprache umzusetzen
Wenn man in so einer Situation Go gewählt hat, war die Sprachwahl selbst wohl das Problem. C/C++/Rust/Zig wären dafür besser geeignet
Es gibt Hinweise, dass der neue Garbage Collector „Green Tea“ helfen könnte. Er ist zwar nicht primär auf Speicher optimiert, aber ein paralleler Markierungsalgorithmus, der mit speicherbenachbarten Objekten besser umgeht. Weitere Informationen gibt es hier
Das Arena-Experiment lief zwar eine Zeit lang, ist derzeit aber gestoppt. Trotzdem interessant genug, um es sich anzusehen
Sorry, dass das nicht besonders hilfreich ist, aber angesichts der aktuellen Lage denke ich, dass die Sprachwahl komplett falsch war. Ich vermute, dass ihr Go nur wegen einer offiziellen Sprachrichtlinie im Unternehmen erzwingt. In großen Firmen wird Produktion oft nur für weit verbreitete Sprachen freigegeben
Ich verstehe bis heute nicht, warum
deferin Go nur auf Funktions-Scope und nicht auf lexikalischen Scope wirkt. Gemerkt habe ich mir das, nachdem ich in einer Schleife Dateien verarbeitet habe, die Dateiliste groß wurde unddeferdie Handles nicht vor Funktionsende schloss, was zu einem Crash führte. Andere Go-Entwickler meinten dann, ich solle einfach den Schleifenrumpf in eine anonyme Funktion packen. Abgesehen von ein paar kleineren Punkten fühlt sich Go ansonsten angenehm an, hat eine effiziente Syntax und verhindert auch unnötige „Angeber“-Kultur. Ich habe einmal ein großes C#-Projekt in Go neu geschrieben; obwohl es nur ein Zehntel des Funktionsumfangs hatte, war der Code trotzdem kürzer. Statt GC-Allokationen zu erzwingen, lenkt Go einen dazu, standardmäßig performante Muster zu verwenden, und eingebaute Codegenerierung für Dinge wie Serialisierung ist praktisch. Anders als bei der C#-Syntax, die alles durch die Sprache selbst ersetzen will, schreibt man in Go SQL einfach als SQL, und gRPC wird über die protobuf-Spezifikation abgewickeltManchmal braucht man
deferauf lexikalischem Scope, manchmal auf Funktions-Scope. Wenn man zum Beispiel in einer Schleife mehrere Dateien öffnet und sie bis zum Ende der Funktion alle offen halten will, braucht man Funktions-Scope. Aktuell ist es eben Funktions-Scope; wenn man lexikalischen Scope braucht, kann man mitfunckapseln. Wenn nur lexikalischer Scope unterstützt würde und man Funktions-Scope bräuchte, wäre unklar, wie man das lösen sollteVorteile sind, dass man ohne Wrapper-Funktion eine zusätzliche Einrückungsebene spart, dass das Verhalten mit Call-Stack und Stack-Unwinding zusammenhängt und dass es aus Sicht des C-Stils mit
goto failnatürlich wirkt. Klar, in Schleifen istdeferetwas unpraktisch, weil man dort extra in eine Funktion kapseln mussIch habe sowohl Sprachen mit Block-Level- als auch mit Function-Level-
deferbenutzt, und manchmal wünschte ich, man könnte auch inif-Blöcken Function-Level-deferverwendenIch glaube nicht, dass es dafür einen besonders tiefen Grund gibt, und frage mich, ob das in der Praxis überhaupt wichtig ist
Auch in C# kann man mit SQL oder protobuf-Spezifikationen arbeiten. Der Unterschied ist nur, dass es daneben noch andere Optionen gibt
Go hat viele Schwächen, aber in der Kategorie serverseitiger Sprachen wirkt es auf mich wie die ausgewogenste Sprache. Es ist schneller als Node oder Python, und das Typsystem ist meiner Meinung nach auch besser. Die Einstiegshürde ist niedriger als bei Rust, und Standardbibliothek sowie Tooling sind hervorragend. Ich mag die einfache Syntax und dass im Grunde ein einziger Weg vorgegeben wird. Die Fehlerbehandlung ist problematisch, aber immer noch besser als bei Node, wo in
catchsonstwas landen kann. Ich frage mich, ob es noch eine bessere Sprache gibt, die all diese Kriterien erfüllt. Ich bin kein Go-Fanatiker; ich habe den Großteil meiner Laufbahn Backend mit Node gemacht, experimentiere aber in letzter Zeit mit GoEigentlich ließen sich all diese Vorteile genauso auf Java oder C# anwenden
Mich stört schon,
Nodeals Programmiersprache zu bezeichnen. Node ist eine JavaScript-Runtime, und viele heutige Projekte auf Node sind in TypeScript geschrieben. Das heißt: Wenn man Node sagt, ist die verwendete Sprache gar nicht eindeutig. Nimmt man TypeScript als Maßstab, finde ich dessen Typsystem sogar produktiver als das von Go. Dasselbe Argument lässt sich auch im Vergleich zu Rust machenDie meisten Sprachen haben ihre eigenen unbequemen Seiten. Go punktet mit Performance, Portabilität sowie Laufzeit und Ökosystem. Andererseits hat es Nachteile wie
nil-Pointer, Zero Values, keine Destruktoren und keine Makros; das Fehlen von Makros wird in Go oft durch exzessive Codegenerierung umgangen. Es gibt bessere Sprachen, etwa Rust, aber die sind dann auch deutlich komplexer als Go. Der Grund dafür ist, dass die Go-Macher Einfachheit über alles gestellt habenWenn man die jüngsten Fortschritte beim Typsystem von Python berücksichtigt, liegt es meiner Ansicht nach weit vor Go. Allein beim Structural Typing ist Python beeindruckender
Ich halte das Typsystem von Go für ziemlich unzureichend
Ich habe einmal einen in Go geschriebenen Static Site Generator erweitert. Der Code war sehr klar und gut lesbar, aber wegen sprachlicher Lücken schlecht erweiterbar. Selbst einfache Änderungen zwangen dazu, an vielen Stellen mühsam umzubauen. Verschiedene Ebenen von Kapselung und Abstraktion sind schwierig, und zugunsten von „Einfachheit“ wird Abstraktion geopfert. Dabei ist Abstraktion der wichtigste Weg, Code zu schreiben, der leicht erweitert werden kann. Go entscheidet sich also für Einfachheit statt Erweiterbarkeit. Meist wirkt ein Go-Programm auf mich wie „einfache, aber nicht erweiterbare“ Software. Viele sagen dann einfach, Go sei eben so, aber meine Erfahrung überzeugt mich davon nicht. Immerhin ist die „Developer Experience“ nicht schlecht
Gespräche über Go fühlen sich immer etwas seltsam an. Wenn man Kritik übt, kommt meist nur „die Sprache ist halt so“, und man soll sich damit abfinden. Einfachheit wird als Stärke verkauft, aber ist es wirklich einfacher, eine Schlüsselliste aus einer Map zu bekommen, wenn man dafür selbst eine Schleife schreiben muss?
Ich frage mich, ob man nach nur kurzem Kontakt mit Go wirklich so ein Urteil fällen kann. Ich arbeite seit 2015 mit zahlreichen großen Go-Codebasen in der Größenordnung von Millionen Zeilen und in mehreren Teams. Was Erweiterbarkeit angeht, ist Go im Vergleich zu C, C# oder Java keineswegs besonders schwach. Go bevorzugt Klarheit gegenüber Ausdrucksstärke. Deshalb hat man weniger Abstraktionsschichten und gewöhnt sich daran, konkreter und expliziter zu schreiben. Aber ich sehe darin keinen Beleg, dass es nicht erweiterbar sei. Modulare, erweiterbare Architektur ist eher etwas, das Entwickler lernen und umsetzen, nicht etwas, das die Sprache allein liefert. Vielleicht war der Code, den du bearbeitet hast, einfach schlecht entworfen; das ist keine Grenze der Sprache selbst
Ich habe Go einige Jahre lang verwendet. Kleine Dinge kann man schnell bauen, aber je größer das Projekt wird, desto mehr leidet man unter unzähligen kleinen Unbequemlichkeiten. Besonders Debugging ist ein Albtraum: Wenn es ein unbenutztes X gibt, was beim Auskommentieren einzelner Stellen während des Debuggens ständig passiert, kompiliert das Programm überhaupt nicht mehr. Auch unnötige Förmlichkeit, spezielle Dateinamen und viele reservierte Feldnamen sind lästig. Versteckte
panics in der Standardbibliothek und unerwartete Heap-Kopien machen es ebenfalls langsam und nervig. Die „magischen“ Teile von Go sind meist Nebenwirkungen davon, dass man bestehende Mechanismen wie spezielle Dateinamen oder Groß-/Kleinschreibung zweckentfremdet hat. Wenn etwas wirklichpublicsein soll, hätte man auch einfachpubschreiben können; diese Sturheit wirkt seltsam. Heute ist KI so gut, dass ich bei Typfehlern oder Borrow-Checker-Problemen in Rust direkt die KI frage und schnell weiterkomme. Ich muss nicht mehr wie früher Zeit damit vergeuden, Dokumentation oder Stack Overflow zu durchforstenIch habe Rust noch nicht intensiv verwendet, aber als ich es letzten Dezember kurz ausprobierte, war ich überrascht, wie gut KI mit Rust zurechtkommt. Gerade weil es so viele präzise Syntaxdetails und explizite Typinformationen gibt, löst KI das teils besser als Menschen
Wenn man sich in Go über Compile-Fehler beim Debuggen beschwert, bekommt man aus dem Go-Lager oft nur zu hören, man solle eben die richtigen Tools benutzen. Prinzipien werden dort zu extrem durchgezogen, und das ist unerquicklich
Ich habe diese Debugging-Unbequemlichkeit einmal einem der Go-Erfinder geschildert, aber selbst der konnte das Problem nicht nachvollziehen. Das wirkte sehr amateurhaft und war enttäuschend. Übrigens ist KI in Go eher nicht so gut. Obwohl die Sprache recht einfach ist, unterstützt ChatGPT Java, C# und Python besser
Persönlich mag ich Go nicht besonders und sehe viele gravierende Schwächen, aber warum es weiter so beliebt ist, ist klar. Go ist relativ schnell und erlaubt dank Goroutines, auch ohne Multithreading stabile und zuverlässige hochgradig nebenläufige Services einfach zu schreiben. Als Google Go veröffentlichte, gab es kaum vergleichbare populäre, statische, kompilierte Sprachen. Selbst heute ist Java der einzige ernsthafte Konkurrent in ähnlicher Position, inzwischen mit Virtual Threads. Sprachen mit async/await versprechen Ähnliches, bringen in der Praxis aber viel Komplexität mit, etwa kein Blocking in asynchronen Tasks oder die bekannte Function Coloring. Erlang ist wieder eine andere Kategorie. Letztlich bleibt Go trotz seiner vielen Schwächen wegen Goroutines und der Strahlkraft eines Google-Projekts populär
Die JVM verringert den Abstand zu Go schrittweise. Mit Projekten wie Virtual Threads, zgc, lilliput, Leyden und Valhalla wird sie immer besser. Der Wandel von Java 8 zu 25 ist enorm. In Zukunft dürfte es noch komfortabler werden
Gos Explizitheit und Einfachheit passen sehr gut zu LLM-gestütztem Programmieren. Alter Go-1.x-Code läuft auch heute noch problemlos auf aktuellen Versionen
Tatsächlich wird intern bei Google Java mit Virtual Threads viel häufiger verwendet als Go
Mich würde interessieren, welche „moderne Sprache“ du für neue Projekte am geeignetsten hältst
Ich mochte Go schon vor 1.0, aber der Vorwurf „es ist immer noch nicht fertig“ leuchtet mir nicht ein. Natürlich gibt es Schwächen und Frustpunkte, aber wenn die Gründer ein Projekt verlassen, wird es auch schwerer, eine zentrale Vision zu halten, und das Risiko steigt, dass die Sprache schlechter wird. Dass Go nur als „Serversprache“ positioniert wird, dürfte am Ende eher dazu führen, dass Leute zu Rust oder Python abwandern. Über Visual Basic wurde früher auch gespottet, und trotzdem haben die Leute, die es brauchten, gut damit gearbeitet
Wenn man kritische Texte über die Schwächen von Go genau prüft, sind viele Punkte eigentlich keine große Sache. Meist sind sie technisch korrekt, aber eher nebensächlich. Wirklich gravierende Sprachdesign-Probleme sind stattdessen Zero Values, fehlende Unterstützung für Konstruktoren, schwache Null-Behandlung, standardmäßige Mutability, ein nicht mit Blick auf Generics entworfenes Typsystem,
intohne beliebige Präzision und Slices mit unklaren Eigentumsverhältnissen (relevantes Issue 1, relevantes Issue 2). Auch fehlende Sum Types und keine String-Interpolation sind NachteileIch bin vielleicht voreingenommen genug, um ein Buch über Go zu schreiben, aber nach mehr als zehn Jahren mit Go erinnere ich mich noch gut daran, wie frisch es sich anfangs anfühlte. Weniger Boilerplate als Java, leicht zu lernen und ordentliche Performance. Die beste Sprache gibt es nicht; je nach Einsatzzweck gibt es die passendste Wahl. Für typische Backend-Arbeit ist Go aber eine Entscheidung, die man kaum bereut