5 Punkte von GN⁺ 2025-08-23 | Noch keine Kommentare. | Auf WhatsApp teilen
  • 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

Zwei Formen von nil

  • In Go gibt es die verwirrende Situation, dass nil bei Interface-Typen und Pointer-Typen unterschiedlich funktioniert
    • Wie im folgenden Beispiel führen Zuweisungen von nil an s (Pointer) und i (Interface) zu inkonsistentem Verhalten, etwa weil s==i unterschiedlich 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

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 append und 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 append auf einen Slice in der Funktion foo tatsächlich auf das Original hat
    • Dadurch nimmt die Zahl sprachlicher „quirks“ zu, die man kennen muss, und das führt zu Fehlern

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 defer freigegeben 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

Ausnahmebehandlung in der Standardbibliothek

  • Go ist strukturell so angelegt, dass es keine expliziten Exceptions unterstützt, dennoch treten Ausnahmefälle wie panic weiterhin auf
    • In manchen Situationen beendet panic das 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

UTF-8-Verarbeitung und Strings

  • Selbst wenn man beliebige Binärdaten in den Typ string steckt, 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

Noch keine Kommentare.

Noch keine Kommentare.