7 Punkte von GN⁺ 2026-02-18 | 1 Kommentare | Auf WhatsApp teilen
  • Mit Go 1.26 wird der vollständig neu geschriebene Befehl go fix eingeführt, der Code mithilfe aktueller Sprach- und Bibliotheksfunktionen automatisch verbessern kann
  • Das Tool erkennt über Dutzende Analyzer Code-Muster und wendet verschiedene Modernizer wie minmax, rangeint und stringscut an, um wiederholten oder veralteten Code in moderne Formen zu überführen
  • Zur Unterstützung der neuen Funktion new(expr) wurde der Analyzer newexpr hinzugefügt, der Hilfsfunktionen wie newInt automatisch vereinfachen kann
  • Mehrfaches Ausführen von go fix erzeugt Synergieeffekte: Unterschiedliche Analyzer können nacheinander Verbesserungen vorschlagen; außerdem sind automatische Zusammenführung bei Konflikten und das Entfernen unnötiger Imports enthalten
  • Das Go-Team plant künftig eine Erweiterung über ein „Self-service“-Analyseparadigma, damit Entwickler Modernizer für ihre eigenen APIs definieren und verteilen können

Überblick über den Befehl go fix

  • In Go 1.26 wurde go fix vollständig neu implementiert und bietet nun die automatische Umwandlung von Codebasen in einen aktuellen Go-Stil
    • Mit dem Befehl go fix ./... werden alle Pakete unterhalb des aktuellen Verzeichnisses angepasst
    • Mit der Option -diff lassen sich Änderungen vorab anzeigen
  • Die Liste der registrierten Analyzer lässt sich mit go tool fix help anzeigen und umfasst verschiedene Transformationsregeln wie any, forvar, mapsloop und minmax
  • Um nur einen bestimmten Analyzer auszuführen, wird ein Flag wie -any verwendet; zum Ausschließen -any=false
  • Unter Berücksichtigung plattformspezifischer Code-Unterschiede ist eine mehrfache Ausführung für verschiedene GOOS-/GOARCH-Kombinationen möglich

Modernizer — Werkzeuge zur Code-Modernisierung

  • Seit der Einführung von Generics ab Go 1.18 ist das Potenzial zur Vereinfachung von Code deutlich gestiegen
    • Beispiel: Sammeln von Map-Schlüsseln mit maps.Keys, Aufteilen von Strings mit strings.Cut
  • Um das Problem zu beheben, dass LLM-basierte Codegenerierungs-Tools veraltete Muster beibehalten, wird die Notwendigkeit betont, Open-Source-Code mit aktuellen Go-Idiomen zu aktualisieren
  • Die in go fix und gopls enthaltenen Modernizer verbessern Lesbarkeit und Lerneffekt des Codes
  • Beispielhafte Modernizer:
    • minmax: Ersetzt if-Anweisungen durch min-/max-Funktionen
    • rangeint: Wandelt dreiteilige for-Schleifen in range-over-int um
    • stringscut: Vereinfacht auf strings.Index basierenden Code mit strings.Cut

Die Funktion new(expr) in Go 1.26

  • Die Funktion new wurde erweitert, sodass sie Wertargumente zulässt und eine Initialisierung in der Form new("go1.26") ermöglicht
  • Der Analyzer newexpr findet Hilfsfunktionen wie newInt, vereinfacht sie zu return new(x) und ersetzt Aufrufstellen durch new(expr)
  • Die Anwendung erfolgt nur, wenn die minimale Go-Version erfüllt ist (z. B. mit der Direktive go 1.26)
  • Mit dem Befehl $ go fix -newexpr ./... lässt sich dies auf die gesamte Codebasis anwenden
  • Nach der Anwendung können unnötige Hilfsfunktionen mit dem Tool deadcode identifiziert werden

Synergien und Konfliktbehandlung

  • Eine einzelne Änderung kann Synergieeffekte erzeugen und neue Möglichkeiten für weitere Änderungen schaffen
    • Beispiel: Nach Anwendung von minmax werden zusätzliche Transformationen vorgeschlagen
    • Möglich sind auch aufeinanderfolgende Optimierungen wie stringsbuilderfmt.Fprintf
  • go fix verwendet einen 3-Wege-Merge-Algorithmus, um Änderungskonflikte automatisch zusammenzuführen
    • Bei Syntaxkonflikten wird die betreffende Änderung übersprungen und eine Warnung ausgegeben
    • Semantische Konflikte (z. B. entfernte Variablen oder ungenutzte Imports) erfordern manuelle Anpassungen
    • Unnötige Imports werden automatisch entfernt

Integration in das Go-Analyse-Framework

  • go vet und go fix wurden so integriert, dass sie ein gemeinsames Analyse-Framework nutzen
    • vet konzentriert sich auf die Fehlererkennung, fix auf sichere automatische Korrekturen
  • Analyzer können über verschiedene Treiber ausgeführt werden, darunter unitchecker, multichecker, gopls, staticcheck und Tricorder
  • Über das Fact-System ist ein Informationsaustausch zwischen Paketen möglich
    • Beispiel: Es lässt sich ableiten, dass log.Printf ein Wrapper von fmt.Printf ist
  • gopls bietet Echtzeitdiagnosen und Vorschläge für automatische Korrekturen

Verbesserungen an der Analyse-Infrastruktur

  • Durch die Erweiterung des Pakets inspector wurde die Effizienz der AST-Durchsuchung verbessert; der Typ Cursor unterstützt Navigation nach oben, unten, links und rechts
  • Die Indizierung von Funktionsaufrufen über typeindex erhöht die Analysegeschwindigkeit um bis zu das 1000-Fache
  • Weitere Verbesserungen:
    • Bereitstellung eines Abhängigkeitsgraphen der Standardbibliothek
    • Unterstützung für Go-Versionsabfragen pro Datei
    • Ausbau von Refactoring-Primitiven, um sichere Codeänderungen wie das Auskommentieren zu ermöglichen
  • Einige Modernizer wurden wegen subtiler Verhaltensänderungen ausgeschlossen (Beispiel: append([]string{}, slice...)slices.Clone(slice))
  • Geplant sind außerdem eine Pattern-Matching-Engine, ein automatisches Test-Harness und eine Bibliothek präziser Änderungsoperatoren

Das Self-service-Paradigma

  • Ab Go 1.26 wird die Einführung eines Self-service-Analysemodells angekündigt
    • Entwickler können Modernizer für ihre eigenen APIs definieren und verteilen
    • Die Ausführung ist auf Projektebene ohne zentrales Freigabeverfahren möglich
  • Als erster Schritt ist eine Annotation-driven inliner-Funktion als Vorschau enthalten
  • Zukünftige Pläne:
    • Ausführung benutzerdefinierter Analyzer per dynamischem Laden (innerhalb von go fix oder gopls)
    • Verallgemeinerung kontrollflussbasierter Checks, z. B. Prüfung von Invarianten wie „open vor close“ oder „lock vor unlock“
  • Ziel ist eine höhere Wartungseffizienz und die schnellere Einführung neuer Go-Funktionen

1 Kommentare

 
GN⁺ 2026-02-18
Hacker-News-Kommentare
  • Als sich LLM-Code-Assistenten Ende 2024 rasant verbreiteten, war interessant zu sehen, dass solche Tools dazu neigen, den bestehenden Go-Code-Stil aus ihren Trainingsdaten unverändert nachzubilden
    Selbst wenn man sie anwies, moderne Syntax zu verwenden, ignorierten sie das oft oder bestritten sogar, dass es sie überhaupt gibt
    Damit künftige Modelle die neuesten Go-1.25-Idiome widerspiegeln, muss der gesamte Open-Source-Code auf diesen Stil aktualisiert werden

    • Auch bei PHP gab es früher Versuche, veraltete Ratschläge von Stack Overflow aufzuräumen, etwa magic_quotes
      Aber wenn einmal falsche Daten in ein LLM eingeflossen sind, ist eine Korrektur fast unmöglich
      Es ist schwer nachzuverfolgen, auf welcher Grundlage das Modell zu seinen Schlussfolgerungen kommt, und man kann nur hoffen, dass es in der nächsten Modellgeneration behoben wird
    • Von LLMs erzeugter Go-Concurrency-Code ist besonders gefährlich
      Er wirkt simpel und kommt durch Reviews, in Wirklichkeit fehlen aber Fehlerbehandlung und Edge Cases
      Gibt man den Code nach dem Review erneut an ein LLM, bekommt man scheinbar korrigierten Code zurück, in dem dann jedoch Data Races oder Deadlocks entstehen
      Das ist ein Problem, das sich bei fast allen Modellen wiederholt
    • Ich habe solche Probleme auch oft erlebt
      Go ist dank seiner Abwärtskompatibilität so stabil, dass der Code zwar kompiliert, sich der Stil aber stark unterscheidet
      Bei Python führen API-Änderungen zu echten Kompatibilitätsbrüchen
      Trotzdem ist Go wegen seiner Sprachstabilität und Standardbibliothek als Sprache für Codegenerierung hervorragend
    • Der Einsatz von LLMs wird am Ende wohl uniformen und mittelmäßigen Code in großer Menge hervorbringen
    • Ich denke, man sollte die ganze Idee aufgeben, Code mit LLMs zu schreiben
      Wie Rob Pike gewarnt hat, ist diese Technik eine Verschmutzung des Software-Ökosystems
      Viele Menschen wollen den Slop der „Bequemlichkeit“, aber genau das ist der Kern des Problems
  • Ein Tool, das Quellcode automatisch in den neuesten Stil umwandelt, ist wirklich großartig
    OpenRewrite für Java ist ein bekanntes Beispiel, aber für andere Sprachen fällt mir kaum etwas Vergleichbares ein
    Wenn so etwas wie bei Go direkt in die Sprache eingebaut ist, erhöht das die Sprachreife enorm
    Ich vermute, dass neue Sprachen künftig diesen integrierten Ansatz von Go als Vorbild nehmen werden

    • Für C gibt es Coccinelle, vorgestellt auch in diesem LWN-Artikel von 2009
      JetBrains-IDEs können Millionen Zeilen Code auf einmal refaktorisieren oder automatisch in neue Syntax umwandeln
      Es gibt auch Funktionen wie ConvertToPrimaryConstructor
      Außerdem arbeitet Structural Search and Replace nicht auf bloßer Textebene, sondern auf Ebene der Sprachsyntax
      Die Roslyn-Analyzer von .NET bieten in der IDE ebenfalls Vorschläge zur Codekorrektur
      Tutorial-Link
    • clippy für Rust empfiehlt moderne Syntax und kann manches auch automatisch korrigieren
      Dadurch ist der Code deutlich sauberer geworden
    • Auch hlint für Haskell gibt es schon seit Langem
      Es ersetzt etwa concat und map durch concatMap oder vereinfacht unnötige if-Ausdrücke
    • Mich würde interessieren, ob jemand schon einmal eine TypeScript-Codebasis auf diese Weise transformiert hat
      LSP-Server sind funktional schwach und unterstützen nicht einmal grundlegende Refactorings wie das Entfernen von Argumenten
      Ich überlege, ob sich das mit jscodeshift oder in Kombination mit Claude umsetzen ließe
  • Dank solcher Auto-Fix-Tools (go fix) ist Go wirklich eine hervorragende Sprache
    Ich freue mich darauf, dass auch das neue Feature rangeint künftig automatisch über go fix übernommen wird
    Großes Lob an das Go-Team

    • Auch wenn ich oft andere Sprachen verwenden möchte, lande ich wegen der hervorragenden Build-, Test- und Lint-Tools von Go am Ende doch wieder bei Go
      Auch die Kompiliergeschwindigkeit ist kaum zu glauben
    • Früher habe ich for-Schleifen selbst mit regulären Ausdrücken gesucht und geändert, heute erledigt dieses Tool das auf viel elegantere Weise
  • Im Artikel wurde es nicht erwähnt, aber meine Lieblingsfunktion ist die Direktive //go:fix inline
    Sie fügt einzeilige Funktionen beim Aufrufer inline ein
    Damit können Bibliotheksautoren alte Funktionen ganz natürlich automatisch auf neue Versionen migrieren
    Selbst wenn sich die SemVer ändert, ist mit go fix ein automatisches Upgrade möglich

  • In einem kürzlich gesehenen Wes-McKinney-Podcast hieß es, dass Go wegen seines schnellen Compile-Run-Zyklus, des starken Typsystems und der Multithreading-Sicherheit ideal für Coding Agents sei
    Das hat mein Interesse an Go wieder geweckt

  • Das etablierte Tooling und die Konventionen von Go helfen enorm bei agentenbasierter Entwicklung
    Mit go run main.go lässt sich die Entwicklungsumgebung sofort starten, dazu kommen mehrere Worktrees, zentrale Konfiguration und sogar migrierte Datenbanken
    Solche Tools werden in housecat-inc/cheetah geteilt
    Ich denke darüber nach, go fix in den schnellen Zyklus aus go generate, go build, go test und go vet aufzunehmen

    • Die extrem schnelle Kompiliergeschwindigkeit ist auch für iterative Experimente mit LLMs ein großer Vorteil
  • Während ich Python lerne, fällt mir auf, dass es zu viele und uneinheitliche Wege gibt, dieselbe Aufgabe zu lösen
    Fast vermisse ich schon C, wo es nur einen Weg gibt
    Ich frage mich, ob Go diesen Punkt erreicht hat
    Ich möchte wissen, ob es eine Sprache ist, in der man auch ohne Hilfe von LLMs Best Practices befolgen kann

    • Go ist eine ziemlich meinungsstarke Sprache, daher gibt es meist nur einen Weg
      Beeindruckend ist, wie konsequent sie unnötige Komplexität vermeidet und Einfachheit bewahrt
      Ich würde sie jedem empfehlen, der von der Unübersichtlichkeit von Python müde geworden ist
  • Das Konzept eines Self-Service-Analyzers ist wirklich spannend
    Ich kann mir gut vorstellen, dass große Bibliotheks- oder Infrastrukturteams es aktiv einsetzen werden

  • Mit solchen Tools fragt man sich fast, ob nicht auch Sprachen ohne Abwärtskompatibilität praktikabel wären

  • In der TypeScript-Welt übernimmt biome eine ähnliche Rolle
    Es empfiehlt zum Beispiel forEach durch for...of zu ersetzen, und zusammen mit ultracite wird der Workflow deutlich reibungsloser
    In der Datei agents.md habe ich festgehalten: „Nach Änderungen biome fix ausführen“; dadurch bleibt die Codequalität automatisch erhalten
    Im Vergleich zu eslint ist das eine viel leichtere und effizientere Erfahrung